一、第一个窗口程序

一、入口函数

任何平台任何形式的程序都需要入口函数。

一般C/C++程序的入口函数是main。

但Win32程序不是一般C程序。

所以Win32程序的入口函数不是main。

Win32的入口函数叫做WinMain()。

写在MSDN中的官方定义是这个样子:

int WINAPI WinMain(
  HINSTANCE hInstance,  // handle to current instance
  HINSTANCE hPrevInstance,  // handle to previous instance
  LPSTR lpCmdLine,      // pointer to command line
  int nCmdShow          // show state of window
);
hInstance:当前程序运行的实例句柄。

hPrevInstance:之前程序的的实例句柄,在Win32系统中永远赋值为NULL,为兼容旧版Win程序而保留的参数。

lpCmdLine:命令行参数。

nCmdShow:窗口显示的状态,隐藏/最大化/最小化之类的东西。

二、构建窗口

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
	return 0;
}

在这个Win32的入口函数里,我们完全可以和main函数一样,在return 0之前进行各种运算,定义变量,循环,选择,华丽的在函数外定义其他函数然后回来调用竭尽所能,最后单击编译——这都基本不会有任何的大问题——唯一一点的小瑕疵只不过是程序运行后跟个没运行一样而已。

之所以会这样不是程序没有正常运行,程序已经默默的运行完了主函数里的全部代码。

我们熟悉的C/C++程序在运行的时候是依赖于一个控制台或者终端这样的东西,我们的全部数据是借这个终端的平台来进行交互的。

在这个Win32程序中,系统创建了一个进程来执行代码里的全部内容,但不代表系统会自行创建一个窗口,所以在Win32程序中我们必须先创建一个窗口来进行这样的一个数据交互工作。

创建一个窗口大概有这样的几个步骤:

1、注册一个窗口的样式(RegisterClassEx())

2、利用刚创建的窗口样式创建一个窗口实例(CreateWindowEx())

3、消息循环(GetMessage()/TranslateMessage()/DispatchMessage())

每个步骤都对应一个或多个关键函数。


首先是注册窗口函数RegisterClassEx:

这个函数只需要一个类型为WNDCLASSEX的参数。

而WNDCLASSEX是一个结构体,所以我们仅需根据MSDN中的描述将所需创建窗口样式赋值给结构体实例相应变量,传入函数即可。

值得注意的几个属性变量:

cbSize:WNDCLASSEX结构体自身的大小,防止以后对该结构体的扩展

lpszClassName:该注册窗口样式的名称,后面创建窗口则根据该字符串找到该窗口样式

lpfnWndProc:函数指针,指向一个消息处理函数,消息处理函数在后面给出说明


窗口创建函数CreateWindowEx:

HWND CreateWindowEx(
  DWORD dwExStyle,      // extended window style
  LPCTSTR lpClassName,  // pointer to registered class name
  LPCTSTR lpWindowName, // pointer to window name
  DWORD dwStyle,        // window style
  int x,                // horizontal position of window
  int y,                // vertical position of window
  int nWidth,           // window width
  int nHeight,          // window height
  HWND hWndParent,      // handle to parent or owner window
  HMENU hMenu,          // handle to menu, or child-window identifier
  HINSTANCE hInstance,  // handle to application instance
  LPVOID lpParam        // pointer to window-creation data
);


消息处理相关函数:

消息获取函数GetMessage:

BOOL GetMessage(
  LPMSG lpMsg,         // address of structure with message
  HWND hWnd,           // handle of window
  UINT wMsgFilterMin,  // first message
  UINT wMsgFilterMax   // last message
);
第一个参数是一个MSG结构体指针,MSG结构体记录了待处理消息的信息,该函数将得到的消息信息放入该指针指向的MSG结构体空间。

后面三个参数起对消息过滤的作用,一般给定NULL,0,0即可,表示不作过滤。

消息翻译函数TranslateMessage:

BOOL TranslateMessage(
  CONST MSG *lpMsg   // address of structure with message
);
将得到的消息传入该函数作一定处理,再由派发消息函数对该消息调用消息处理函数。

消息派发函数DispatchMessage:

LONG DispatchMessage(
  CONST MSG *lpmsg   // pointer to structure with message
);


三、消息处理函数

LRESULT CALLBACK WindowProc(
  HWND hwnd,      // handle to window
  UINT uMsg,      // message identifier
  WPARAM wParam,  // first message parameter
  LPARAM lParam   // second message parameter
);

这是一个回调函数,需要自行编写,然后将函数地址在注册窗口时赋值给相应的变量,在派发消息函数DispatchMessage中被系统调用。

hwnd是消息的来源窗口句柄。

uMsg是消息标志。

WPARAM与LPARAM则是消息发送时给定的两个参数,不同消息的含义有所不同。


四、代码实例

#include<windows.h>

HINSTANCE g_hInstance=NULL;

LRESULT CALLBACK WindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
	if(uMsg==WM_DESTROY) 
	{
		PostQuitMessage(0);
		return 0;
	}
	return DefWindowProc(hwnd,uMsg,wParam,lParam);
}

ATOM InitApplication(HINSTANCE hInstance)
{
	WNDCLASSEX wcex={0};
	wcex.cbSize       =sizeof(wcex);
	wcex.style        =CS_HREDRAW|CS_VREDRAW;
	wcex.lpfnWndProc  =WindowProc;
	wcex.cbClsExtra   =0;
	wcex.cbWndExtra   =0;
	wcex.hInstance    =hInstance;
	wcex.hIcon        =LoadIcon(NULL,IDI_APPLICATION);
	wcex.hIconSm      =LoadIcon(NULL,IDI_APPLICATION);
	wcex.hCursor      =LoadCursor(NULL,IDC_ARROW);
	wcex.hbrBackground=GetSysColorBrush(COLOR_3DFACE);
	wcex.lpszMenuName =NULL;
	wcex.lpszClassName="MAIN";
	return RegisterClassEx(&wcex);
}

BOOL InitInstance(HINSTANCE hInstance,int nCmdShow)
{
	g_hInstance=hInstance;
	HWND hwndMain=CreateWindowEx(WS_EX_CLIENTEDGE,
								 "MAIN",
								 "MyWin",
								 WS_OVERLAPPEDWINDOW,
								 CW_USEDEFAULT,CW_USEDEFAULT,
								 CW_USEDEFAULT,CW_USEDEFAULT,
								 NULL,
								 NULL,
								 hInstance,
								 NULL);
	if(hwndMain==NULL) return 0;
	ShowWindow(hwndMain,nCmdShow);
	UpdateWindow(hwndMain);
	return 1;
}

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
	if(!InitApplication(hInstance))
		return 0;
	if(!InitInstance(hInstance,nCmdShow))
		return 0;
	MSG Msg={0};
	while(GetMessage(&Msg,NULL,0,0))
	{
		TranslateMessage(&Msg);
		DispatchMessage(&Msg);
	}
	return 0;
}




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值