[Sobin Tech] 用 C 语言编写一个 Windows 程序

在 Windows 编程环境下,编写一个命令行程序依然是简单的,但它并不是最适合这个环境的。 Windows 根本上就是个基于图形化操作的系统,所以即使你是用 GNU 的 gcc 编译器 (MinGW),你依然会得到 windows.h 的支持。

在 Windows 环境中,C 语言并不是图形化开发的最理想工具,VB 和 C# 相比而言更容易使用。但是,作为现代程序员,我们知道,微软很强大,却从来没有独占江山,C 语言的地位并没有因以上两种专属语言的方便优势而降低,仍然是最简洁、应用最广泛的语言。而且由于微软的其它建筑都是以 C 语言为基础的,所以 C 语言的的使用虽然不“方便”(许多 C# 中可以使用绘图工具完成的操作在 C 要通过文字完成),却具有最佳的灵活性。最重要的一点,迄今为止,并没有其他语言在效率上高于 C 。

C 语言可视化程序基本结构

        下面是一个空的可视化程序框架:

#include <windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) {

	return 0;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
	return 0;
}

        这个不是一个完整的程序,因为他不具备任何功能,要想使用它,我们必须在它适当的地方填充一些内容。

        首先,程序的入口不再是 main() 函数,而是 WinMain() 。所以,程序的运行过程就是 WinMain() 函数的运行过程。在 WinMain() 函数里,我们要做以下几点:

                  1. 构造窗体结构;

                  2. 显示窗口;

                  3. 监听和处理窗口事件。

        也许你会注意到 WinMain() 函数的参数列表当中有许多不明类型的参数,显得十分可怕。既然可怕就暂时不去管它,到用的时候我们再解释。

        除了 WinMain() 函数,WndProc() 函数也是必不可少的处理函数,这个函数规定了你的窗体在遇到那些事情的时候该怎么办。这个函数里一般使用一个 switch 结构,讨论其第二个参数 (unsigned int, UINT) 的值,是一个整数,不同的数字表示不同的事件,对于每一种事件我们都对它做出相应的反应,这里就类似于 VB 和 C# 的双击控件设定事件的过程。当然,WndProc() 是用来处理窗体的触发事件的函数,别的控件,比如按钮,会有它独立的处理函数。

        但是,对于一个控件(比如一个按钮),我们可以设置的事件可能有多种,比如左击、右击等,我们未必规定了每一种事件(实际上,我们通常只规定其中的一个或很少一部分),剩下的事件交给一个叫做 DefWindowProc() 的函数完成,这个函数的参数列表与 WndProc() 完全一致,返回值可以直接作 WndProc() 的返回值,所以一般 WndProc() 函数的返回值就是一个 DefWindowProc() 函数。

        计算机是一个过程处理中心,它并不是一个被动的机器,而是一个主动的机器,但由于可视化的应用程序呈现的是一个被动的操作界面(比如你点一个按钮,才发生了一个事件),这种模式叫“触发”,启动触发事件的机关叫“触发器”。计算机作为主动的机器,是通过不间断的“监听”来完成触发的模拟,“监听”就是不断地检查窗体有没有被“触”(比如不断的检查某个按钮那块区域是否被点击了),一旦发现了所监听的事件,就立刻调用相关过程作出反应,这就是触发模拟的基本原理。所以,“处理窗口事件”就是不断地循环检查并作出反应,直到程序结束的过程。但由于图形操作面临两个事件同时被触发的问题,这就是多线程问题,这一点在 Windows 现有的机制下已经被巧妙的解决,我们所使用的函数中已经蕴含了相关的方法,只是我们看不见。

        下面转载一个实例(来源:https://www.cnblogs.com/mr-wid/archive/2012/10/08/2715673.html),供大家参考:

#include <windows.h>

LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM );        //声明用来处理消息的函数

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow ) {
	static TCHAR szAppName[] = TEXT("MyWindow") ;
	HWND hwnd ;
	MSG msg ;
	WNDCLASS wndclass ;

	//以下为窗口类对象wndclass的属性
	wndclass.style = CS_HREDRAW | CS_VREDRAW ;                         //窗口样式
	wndclass.lpszClassName = szAppName ;                               //窗口类名
	wndclass.lpszMenuName = NULL ;                                     //窗口菜单:无
	wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH) ;    //窗口背景颜色
	wndclass.lpfnWndProc = WndProc ;                                   //窗口处理函数
	wndclass.cbWndExtra = 0 ;                                          //窗口实例扩展:无
	wndclass.cbClsExtra = 0 ;                                          //窗口类扩展:无
	wndclass.hInstance = hInstance ;                                   //窗口实例句柄
	wndclass.hIcon = LoadIcon( NULL, IDI_APPLICATION ) ;               //窗口最小化图标:使用缺省图标
	wndclass.hCursor = LoadCursor( NULL, IDC_ARROW ) ;                 //窗口采用箭头光标

	if( !RegisterClass( &wndclass ) ) {
		//注册窗口类, 如果注册失败弹出错误提示
		MessageBox(NULL, TEXT("窗口注册失败!"), TEXT("错误"), MB_OK | MB_ICONERROR ) ;
		return 0 ;
	}

	hwnd = CreateWindow(                   //创建窗口
	           szAppName,                 //窗口类名
	           TEXT("My Application Window"),//窗口标题
	           WS_OVERLAPPEDWINDOW,       //窗口的风格
	           CW_USEDEFAULT,             //窗口初始显示位置x:使用缺省值
	           CW_USEDEFAULT,             //窗口初始显示位置y:使用缺省值
	           CW_USEDEFAULT,             //窗口的宽度:使用缺省值
	           CW_USEDEFAULT,             //窗口的高度:使用缺省值
	           NULL,                      //父窗口:无
	           NULL,                      //子菜单:无
	           hInstance,                 //该窗口应用程序的实例句柄
	           NULL                       //
	       ) ;

	ShowWindow(hwnd, iCmdShow) ;        //显示窗口
	UpdateWindow(hwnd) ;                //更新窗口

	while(GetMessage(&msg, NULL, 0, 0)) {      //从消息队列中获取消息
		TranslateMessage(&msg);                 //将虚拟键消息转换为字符消息
		DispatchMessage(&msg);                  //分发到回调函数(过程函数)
	}
	return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
	HDC hdc ;                //设备环境句柄
	PAINTSTRUCT ps ;         //绘制结构
	RECT rect;               //矩形结构

	switch(message) {      //处理得到的消息
		case WM_CREATE:          //窗口创建完成时发来的消息
			MessageBox( hwnd, TEXT("Created Window!"), TEXT("My window"), MB_OK | MB_ICONINFORMATION ) ;
			return 0;

		case WM_PAINT:           //处理窗口区域无效时发来的消息
			hdc = BeginPaint( hwnd, &ps ) ;
			GetClientRect( hwnd, &rect ) ;
			DrawText( hdc, TEXT( "Hello, My window!" ), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER ) ;
			EndPaint( hwnd, &ps ) ;
			return 0 ;

		case WM_LBUTTONDOWN:     //处理鼠标左键被按下的消息
			MessageBox( hwnd, TEXT("Left Clicked."), TEXT("Click Event"), MB_OK | MB_ICONINFORMATION ) ;
			return 0;

		case WM_DESTROY:         //处理窗口关闭时的消息
			MessageBox( hwnd, TEXT("End!"), TEXT("END"), MB_OK | MB_ICONINFORMATION ) ;
			PostQuitMessage( 0 ) ;
			return 0;
	}
	return DefWindowProc(hwnd, message, wParam, lParam);//DefWindowProc处理我们自定义的消息处理函数没有处理到的消息
}



       

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值