创建一个window窗口:
创建一个窗体,必须先注册,再创建,后显示。需要用到:
RegisterClassEx、CreateWindowEx、ShowWindow、UpdateWindow定义在windows.h
1.注册一个window类:
- ATOM RegisterClassEx(CONST WNDCLASSEX *Ipwcx);
参数:
WNDCLASSEX:一个结构体,描述了窗口的一些行为特征,例如鼠标,光标的长相之类的,还指定了谁处理它的事件(一个回调函数)
- WNDCLASSEX wc;
- wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
- wc.lpfnWndProc = WndProc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = m_hinstance;
- wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
- wc.hIconSm = wc.hIcon;
- wc.hCursor = LoadCursor(NULL, IDC_ARROW);
- wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
- wc.lpszMenuName = NULL;
- wc.lpszClassName = m_applicationName;
- wc.cbSize = sizeof(WNDCLASSEX);
参数:
wc.hInstance:应用程序实例句柄,一个应用程序是可以有多个窗体的,这里指定此窗体是属于那个应用实例的。应用实例的获取:GetModuleHandle(NULL); 参数为null就是获取当前应用。
wc.lpfnWndProc:指定一个回调函数,这个回调函数用于处理事件。
wc.style:窗口的显示样式。有以下这些类型:
- #define CS_VREDRAW 0x0001 // 垂直变化时,重绘
- #define CS_HREDRAW 0x0002 // 水平变化时,重绘
- #define CS_KEYCVTWINDOW 0x0004
- #define CS_DBLCLKS 0x0008 // 不忽略鼠标双击的消息
- #define CS_OWNDC 0x0020 // 给用该类建立的每一个窗口分配独立的设备 DC
- #define CS_CLASSDC 0x0040 // 让属于该类的所有窗口共享一个设备 DC
- #define CS_PARENTDC 0x0080 // 允许窗口的子窗口继承一些共同特性
- #define CS_NOKEYCVT 0x0100
- #define CS_NOCLOSE 0x0200 // 禁用系统菜单的 Close命令,同时窗口没有关闭按钮
- #define CS_SAVEBITS 0x0800 // 当窗口被覆盖时, 用位图缓存被覆盖区, 从而避免 WM_PAINT 消息, 一般用于菜单或对话框
- #define CS_BYTEALIGNCLIENT 0x1000
- #define CS_BYTEALIGNWINDOW 0x2000
- #define CS_GLOBALCLASS 0x4000 // 全局窗口类, 一般用于 DLL; 没有此选项, 窗口类和窗口建立函数中指定的实例句柄须相同
- #define CS_IME 0x00010000
DC:又称设备场景,GUI里面的一个概念,相当于真正绘制工具的一个描述它的结构,里面有背景颜色之类的属性。
2.创建和显示window窗体:
- HWND CreateWindowEx(
- DWORD dwExStyle,
- LPCTSTR lpClassName,
- LPCTSTR lpWindowName,
- DWORD dwStyle,
- int x,
- int y,
- int nWidth,
- int nHeight,
- HWND hWndParent,
- HMENU hMenu,
- HINSTANCE hInstance,
- LPVOID lpParam
- );
dwExStyle:比较常用的样式,dwExStyle的样式都有_EX
- WS_EX_ACCEPTFILES
- WS_EX_APPWINDOW
- WS_EX_CLIENTEDGE
- WS_EX_DLGMODALFRAME
- WS_EX_CONTEXTHELP
- WS_EX_WINDOWEDGE
dwStyle:比较常用的样式
- WS_BORDER
- WS_CAPTION
- WS_HSCROLL
- WS_MAXIMIZE
- WS_VSCROLL
实例:
- HWND m_hwnd = CreateWindowEx(WS_EX_APPWINDOW, m_applicationName, m_applicationName,
- WS_OVERLAPPEDWINDOW,
- posX, posY, screenWidth, screenHeight, NULL, NULL, m_hinstance, NULL);
-
- ShowWindow(m_hwnd, SW_SHOW);
- SetForegroundWindow(m_hwnd);
- SetFocus(m_hwnd);
- UpdateWindow(m_hwnd);
3.创建全屏窗体:其基本思路是零时对显示设备的属性进行修改,并且制定显示模式。
- LONG ChangeDisplaySettings (LPDEVMODE lpDevMode, DWORD dwflags);
lpDevMode:是一个EVMODE类型的结构体的指针。
dwflags:表明了图形模式如何改变。关于这个两个参数的具体细节可参考:
http://baike.baidu.com/view/1080516.htm
-
- DEVMODE dmScreenSettings;
- memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
- dmScreenSettings.dmSize = sizeof(dmScreenSettings);
- dmScreenSettings.dmPelsWidth = (unsigned long)screenWidth;
- dmScreenSettings.dmPelsHeight = (unsigned long)screenHeight;
- dmScreenSettings.dmBitsPerPel = 32;
- dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
-
-
- ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN);
注意:临时设置显示设备是在创建窗体之前。在调用CreateWindowEx方法前面加上这些就行了。
4.消息循环:
消息结构:
- typedef struct tagMSG {
- HWND hwnd;
- UINT message;
- WPARAM wParam;
- LPARAM lParam;
- DWORD time;
- POINT pt;
- } MSG;
消息循环:
- MSG msg;
- bool done=false, result = 1;
-
-
- ZeroMemory(&msg, sizeof(MSG));
-
-
- while(!done)
- {
-
- if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
-
-
- if(msg.message == WM_QUIT)
- {
- done = true;
- }
- }
PeekMessage:获取消息,还有一种方式,可以到网上查找。
TranslateMessage:组合消息,例如把按下和弹起合并为一个消息
DispatchMessage:处理消息,这个时候会调上面提到的那个回调函数。
消息处理回调函数:
- LRESULT CALLBACK WndProc(HWND hwnd, UINT umessage, WPARAM wparam, LPARAM lparam)
- {
- switch(umessage)
- {
-
- case WM_DESTROY:
- {
- PostQuitMessage(0);
- return 0;
- }
-
- default:
- {
-
- return DefWindowProc(hwnd, umsg, wparam, lparam);
- }
- }
- }
这里需要注意的第一个就是函数的参数,就是上面MSG结构里面的几个值。另外就是PostQuitMessage的作用相当于发出一个WM_QUIT消息,参数0是消息码。DefWindowProc是window默认处理消息的函数,所有程序不想处理的消息都给它处理。
5.销毁应用实例:
- UnregisterClass(m_applicationName, m_hinstance);