引用:http://blog.csdn.net/jarvischu/article/details/8115390
1. 程序
-
-
-
-
-
-
-
-
-
-
- #include <windows.h>
- #include <stdio.h>
- #include "resource.h"
-
-
- LRESULT CALLBACK WinProc(
- HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam
- );
-
-
- int WINAPI WinMain(HINSTANCE hInstance,
- HINSTANCE hPrevInstance,
- LPSTR lpCmdLine,
- int nShowCmd
- )
- {
-
- WNDCLASS wndclass;
- wndclass.cbClsExtra =0;
- wndclass.cbWndExtra =0;
- wndclass.hbrBackground =(HBRUSH)GetStockObject(GRAY_BRUSH);
- wndclass.hCursor =LoadCursor(hInstance,MAKEINTRESOURCE(ID_MYCURSOR));
- wndclass.hIcon =LoadIcon(hInstance,MAKEINTRESOURCE(ID_MYICON));
- wndclass.hInstance =hInstance;
- wndclass.lpfnWndProc =WinProc;
- wndclass.lpszClassName ="Jarvis";
- wndclass.lpszMenuName =NULL;
- wndclass.style =CS_HREDRAW | CS_VREDRAW;
-
-
- RegisterClass(&wndclass);
-
-
- HWND hwnd;
- hwnd=CreateWindow("Jarvis","Jarvis",WS_OVERLAPPEDWINDOW|WS_HSCROLL|WS_MAXIMIZE,
- CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,hInstance,NULL);
-
- ShowWindow(hwnd,SW_SHOWNORMAL);
- UpdateWindow(hwnd);
-
-
- MSG msg;
- while(GetMessage(&msg,NULL,0,0))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- return 0;
- }
-
-
-
- LRESULT CALLBACK WinProc(
- HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam
- )
- {
- switch(uMsg)
- {
-
- case WM_LBUTTONDOWN:
- MessageBox(hwnd,"LeftButton Clicked!","Prompt",0);
- break;
- case WM_CLOSE:
- if(IDYES==MessageBox(hwnd,"Are you sure to quit?","Prompt",MB_YESNO))
- {
- DestroyWindow(hwnd);
- }
- break;
- case WM_DESTROY:
- PostQuitMessage(0);
- break;
- default:
- return DefWindowProc(hwnd,uMsg,wParam,lParam);
-
- }
- return 0;
- }
2. WinMain函数解析
2.1. WinMain函数原型
- int WINAPI WinMain ( HINSTANCE hInstance,
- HINSTANCE hPrevInstance,
- LPSTR lpCmdLine,
- int nShowCmd
- );
2.2. WinMain函数功能
WinMain是一个函数,该函数的功能是被系统调用,作为一个32位应用程序的入口点。WinMain函数应初始化应用程序,显示主窗口,进入一个消息接收-发送循环,这个循环是应用程序执行的其余部分的顶级控制结构。
2.3. 窗口显示方式
WinMain函数的nShowCmd参数指示了窗口的显示方式。显示方式可以是下表中的任何一种。
表格 1 窗口显示方式
SW_HIDE
|
隐藏窗口并且激活另外一个窗口
|
SW_RESTORE
|
激活并显示窗口。如果窗口已经最小化或最大化,系统将以恢复到原来的尺寸和位置显示窗口(与SW_SHOWNORMAL相同)
|
SW_SHOW
|
激活一个窗口并以原来的尺寸和位置显示窗口
|
SW_SHOWMAXIMIZED
|
激活窗口并且将其最大化
|
SW_SHOWMINIMIZED
|
激活窗口并将其最小化(以图标显示)
|
SW_SHOWMINNOACTIVE
|
将一个窗口显示为图标。激活窗口维持活动状态
|
SW_SHOWNA
|
以窗口的当前状态显示窗口。激活窗口保持活动状态
|
SW_SHOWNOACTIVATE:
|
以窗口的最近一次的尺寸和位置显示窗口。激活窗口维持激活状态
|
SW_SHOWNORMAL
|
激活并显示窗口。如果窗口最大化或最小化,系统将其恢复到原来的尺寸和位置(与SW_RESTORE相同)
|
SW_MINIMIZE
|
最小化指定的窗口,并且激活在系统表中的顶层窗口
|
3. 创建和设计窗口类
3.1. WNDCLASS结构体定义
- typedef struct {
- UINT style;
- WNDPROC lpfnWndProc;
- int cbClsExtra;
- int cbWndExtra;
- HINSTANCE hInstance;
- HICON hIcon;
- HCURSOR hCursor;
- HBRUSH hbrBackground;
- LPCTSTR lpszMenuName;
- LPCTSTR lpszClassName;
- } WNDCLASS, *PWNDCLASS;
3.2. 窗口类型
多种窗口类型可以使用 | 号叠加
表格 2 窗口类型
标识
|
描述
|
CS_BYTEALIGNCLIENT
|
在字节边界上(在x方向上)定位窗口的用户区域的位置
|
CS_BYTEALIGNWINDOW
|
在字节边界上(在x方向上)定位窗口的位置
|
CS_CLASSDC:
|
该窗口类的所有窗口实例都共享一个窗口类DC
|
CS_DBLCLKS
|
允许向窗口发送双击鼠标键的消息
|
CS_GLOBALCLASS
|
当调用CreateWindow 或 CreateWindowEx 函数来创建窗口时允许它的hInstance参数和注册窗口类时传递给RegisterClass 的 hInstance参数不同。如果不指定该风格,则这两个 hInstance 必须相同。
|
CS_HREDRAW
|
当水平长度改变或移动窗口时,重画整个窗口
|
CS_NOCLOSE
|
禁止系统菜单的关闭选项
|
CS_OWNDC
|
给予每个窗口实例它本身的DC。注意,尽管这样是很方便,但它必须慎重使用,因为每个DC大约要占800个字节的内存。
|
CS_PARENTDC
|
将子窗口的裁剪区域设置到父窗口的DC中去,这样子窗口便可以在父窗口上绘制自身。注意,这是子窗口还是从系统缓存中获取DC,而不是使用父窗口的DC。使用该风格可以提高系统性能。
|
CS_SAVEBITS
|
以位图形式保存被该窗口遮挡的屏幕部分,这样当给窗口移动以后,系统便可以用该保存的位图恢复屏幕移动的相应部分,从而系统不用向被该窗口遮挡的窗口发送 WM_PAINT 消息。该特性对于菜单类型的窗口比较合适,因为它通常是简短的显示一下之后便消失。设置该特性将增加显示该窗口的时间,因为它通常要先分配保存位图的内存。
|
CS_VREDRAW
|
当垂直长度改变或移动窗口时,重画整个窗口
|
3.3. 窗口图标
3.3.1. LoadIcon函数
- HICON LoadIcon( HINSTANCE Instance,
- LPCTSTR lpIconName
- ) ;
3.3.2. 加载系统预定义图标
- LoadIcon(NULL, IDI_APPLICATION);
表格 3 系统图标资源
IDI_APPLICATION
|
Default application icon.
|
IDI_ASTERISK
|
Same as IDI_INFORMATION.
|
IDI_ERROR
|
Hand-shaped icon.
|
IDI_EXCLAMATION
|
Same as IDI_WARNING.
|
IDI_HAND
|
Same as IDI_ERROR.
|
IDI_INFORMATION
|
Asterisk icon.
|
IDI_QUESTION
|
Question mark icon.
|
IDI_WARNING
|
Exclamation point icon.
|
IDI_WINLOGO
|
Windows logo icon. Windows XP: Default application icon.
|
IDI_SHIELD
|
Security Shield icon.
|
3.3.3. 加载自定义图标
[1] 添加图标资源
File-->New-->Files-->Icon File (Name it “My_Icon.ico” on the right)-->Draw the Icon
[2] 添加资源文件
File-->New-->Files-->Resource Script (Name it “My_Resource”)
打开resource.h 文件,添加语句“#define ID_MYICON 1024”(1024 可以随意)
用记事本打开My_Resource.rc文件,添加语句“ID_MYICON ICON My_Icon.ico”
[3] 添加“resource.h”头文件的引用
在主程序的.cpp文件中,引用头文件“#include “resource.h””
[4] 使用自定义图标
- LoadIcon(hInstance,MAKEINTRESOURCE(ID_MYICON));
3.4. 光标资源
光标资源的加载类似于图标资源
3.4.1. LoadCursor函数
- HCURSOR LoadCursor ( HINSTANCE Instance,
- LPCTSTR lpCursorName
- ) ;
3.4.2. 加载系统预定义光标
- LoadCursor(NULL,IDC_CROSS);
IDC_APPSTARTING
|
Standard arrow and small hourglass
|
IDC_ARROW
|
Standard arrow
|
IDC_CROSS
|
Crosshair
|
IDC_HAND
|
Windows 98/Me, Windows 2000/XP: Hand
|
IDC_HELP
|
Arrow and question mark
|
IDC_IBEAM
|
I-beam
|
IDC_ICON
|
Obsolete for applications marked version 4.0 or later.
|
IDC_NO
|
Slashed circle
|
IDC_SIZE
|
Obsolete for applications marked version 4.0 or later. Use IDC_SIZEALL.
|
IDC_SIZEALL
|
Four-pointed arrow pointing north, south, east, and west
|
IDC_SIZENESW
|
Double-pointed arrow pointing northeast and southwest
|
IDC_SIZENS
|
Double-pointed arrow pointing north and south
|
IDC_SIZENWSE
|
Double-pointed arrow pointing northwest and southeast
|
IDC_SIZEWE
|
Double-pointed arrow pointing west and east
|
IDC_UPARROW
|
Vertical arrow
|
IDC_WAIT
|
Hourglass
|
3.4.3. 加载自定义光标
具体步骤与图标相同(3.3.3)
[1] resource.h

[2] My_Resource.rc

[3] main.cpp

3.5. 背景画刷
背景画刷就是用来设置窗口的背景。
hbrBackground是画刷的句柄,它必须是用于绘制背景的物理刷子的句柄,或者是一个颜色的值。
如果给出一个颜色的值,它必须是下面列出的标准系统颜色之一(系统将对所选颜色加1)。
3.5.1. 使用标准系统颜色
- hbrBackground=(HBRUSH)(COLOR_ACTIVEBORDER+1);
表格 4 标准系统颜色
名称
|
样式
|
名称
|
样式
|
COLOR_ACTIVEBORDER
COLOR_ACTIVECAPTION
COLOR_CAPTIONTEXT
COLOR_WINDOWTEXT
|

|
COLOR_BTNTEXT
COLOR_MENUTEXT
|

|
COLOR_APPWORKSPACE
|

|
COLOR_HIGHLIGHTTEXT
|

|
COLOR_BACKGROUND
COLOR_GRAYTEXT
COLOR_HIGHLIGHT
COLOR_INACTIVEBORDER
|

|
COLOR_INACTIVECAPTION
|

|
COLOR_BTNFACE
COLOR_SCROLLBAR
COLOR_WINDOWFRAME
|

|
COLOR_MENU
|

|
COLOR_BTNSHADOW
COLOR_WINDOW
|

|
|
|
3.5.2. 使用系统预定义的画刷
- hbrBackground =(HBRUSH)GetStockObject(BLACK_BRUSH);
BRUSH
|
名称
|
BLACK_BRUSH
|
黑色画刷
|
DKGRAY_BRUSH
|
暗灰色画刷
|
DC_BRUSH
|
(Win7中错误)
|
GRAY_BRUSH
|
灰色画刷
|
HOLLOW_BRUSH
|
空心刷(相当于NULL_BRUSH)
|
LTGRAY_BRUSH
|
浅灰色画刷
|
NULL_BRUSH
|
空心刷(即背景透明)
|
WHITE_BRUSH
|
白色画刷
|
3.5.3. GetStockObject()函数
- HGDIOBJ GetStockObject(int fnObject);
该函数检索预定义的备用笔、刷子、字体或者调色板的句柄。
fnObject可以是: BLACK_BRUSH,WHITE_PEN,SYSTEM_FONT, DEFAULT_PALETTE
4. 注册窗口类
- ATOM RegisterClass(CONST WNDCLASS *lpWndClass);
窗口只有在其对应的窗口类注册之后,才能使用CreateWindow或CreateWindowEx创建。
5. 创建窗口
- HWND hwnd;
- hwnd = CreateWindow("Jarvis","Jarvis",WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
- CW_USEDEFAULT,NULL,NULL,hInstance,NULL);
- HWND CreateWindow(
- LPCTSTR lpClassName,
- LPCTSTR lpWindowName,
- DWORD dwStyle, / /窗口类型/
- int x,
- int y,
- int nWidth,
- int nHeight,
- HWND hWndParent,
- HMENU hMenu,
- HINSTANCE hInstance,
- LPVOID lpParam
- );
Window_Style(可以组合)
表格 5 Window_Style
Style
|
说明
|
WS_BORDER
|
创建一个单边框的窗口。
|
WS_CAPTION
|
创建一个有标题框的窗口(包括WS_BODER风格)。
|
WS_CHILD
|
创建一个子窗口。这个风格不能与WS_POPUP风格合用。
|
WS_CHLDWINDOW
|
与WS_CHILD相同。
|
WS_CLIPCHILDREN
|
当在父窗口内绘图时,排除子窗口区域。在创建父窗口时使用这个风格。
|
WS_CLIPSIBLINGS
|
排除子窗口之间的相对区域,也就是,当一个特定的窗口接收到WM_PAINT消息时,WS_CLIPSIBLINGS 风格将所有层叠窗口排除在绘图之外,只重绘指定的子窗口。如果未指定WS_CLIPSIBLINGS风格,并且子窗口是层叠的,则在重绘子窗口的客户区时,就会重绘邻近的子窗口。
|
WS_DISABLED
|
创建一个初始状态为禁止的子窗口。一个禁止状态的窗口不能接受来自用户的输入信息。
|
WS_DLGFRAME
|
创建一个带对话框边框风格的窗口。这种风格的窗口不能带标题条。
|
WS_GROUP
|
指定一组控制的第一个控制。这个控制组由第一个控制和随后定义的控制组成,自第二个控制开始每个控制,具有WS_GROUP风格,每个组的第一个控制带有WS_TABSTOP风格,从而使用户可以在组间移动。用户随后可以使用光标在组内的控制间改变键盘焦点。
|
WS_HSCROLL
|
创建一个有水平滚动条的窗口。
|
WS_ICONIC
|
创建一个初始状态为最小化状态的窗口。与WS_MINIMIZE风格相同。
|
WS_MAXIMIZE
|
创建一个初始状态为最大化状态的窗口。
|
WS_MAXIMIZEBOX
|
创建一个具有最大化按钮的窗口。该风格不能与WS_EX_CONTEXTHELP风格同时出现,同时必须指定WS_SYSMENU风格。
|
WS_OVERLAPPED
|
产生一个层叠的窗口。一个层叠的窗口有一个标题条和一个边框。与WS_TILED风格相同。
|
WS_OVERLAPPEDWINDOW
|
创建一个具有WS_OVERLAPPED,WS_CAPTION,WS_SYSMENU WS_THICKFRAME,WS_MINIMIZEBOX,WS_MAXIMIZEBOX风格的层叠窗口,与WS_TILEDWINDOW风格相同。
|
WS_POPUP
|
创建一个弹出式窗口。该风格不能与WS_CHLD风格同时使用。
|
WS_POPUPWINDOW
|
创建一个具有WS_BORDER,WS_POPUP,WS_SYSMENU风格的窗口,WS_CAPTION和WS_POPUPWINDOW必须同时设定才能使窗口某单可见。
|
WS_SIZEBOX
|
创建一个可调边框的窗口,与WS_THICKFRAME风格相同。
|
WS_SYSMENU
|
创建一个在标题条上带有窗口菜单的窗口,必须同时设定WS_CAPTION风格。
|
WS_TABSTOP
|
创建一个控制,这个控制在用户按下Tab键时可以获得键盘焦点。按下Tab键后使键盘焦点转移到下一具有WS_TABSTOP风格的控制。
|
WS_THICKFRAME
|
创建一个具有可调边框的窗口,与WS_SIZEBOX风格相同。
|
WS_TILED
|
产生一个层叠的窗口。一个层叠的窗口有一个标题和一个边框。与WS_OVERLAPPED风格相同。
|
WS_TILEDWINDOW
|
创建一个具有WS_OVERLAPPED,WS_CAPTION,WS_SYSMENU, WS_THICKFRAME,WS_MINIMIZEBOX,WS_MAXMIZEBOX风格的层叠窗口。与WS_OVERLAPPEDWINDOW风格相同。
|
WS_VISIBLE
|
创建一个初始状态为可见的窗口。
|
WS_VSCROLL
|
创建一个有垂直滚动条的窗口。
|
6. 显示窗口
- BOOL ShowWindow(HWND hWnd,
- int nCmdShow
- );
显示方式可以是下表中的任何一种。
表格 6 窗口显示方式
窗口显示方式
|
说明
|
SW_HIDE
|
隐藏窗口并激活其他窗口。
|
SW_MAXIMIZE
|
最大化指定的窗口。
|
SW_MINIMIZE
|
最小化指定的窗口并且激活在Z序中的下一个顶层窗口。
|
SW_RESTORE
|
激活并显示窗口。如果窗口最小化或最大化,则系统将窗口恢复到原来的尺寸和位置。在恢复最小化窗口时,应用程序应该指定这个标志。
|
SW_SHOW
|
在窗口原来的位置以原来的尺寸激活和显示窗口。
|
SW_SHOWDEFAULT
|
依据在STARTUPINFO结构中指定的SW_FLAG标志设定显示状态,STARTUPINFO 结构是由启动应用程序的程序传递给CreateProcess函数的。
|
SW_SHOWMAXIMIZED
|
激活窗口并将其最大化。
|
SW_SHOWMINIMIZED
|
激活窗口并将其最小化。
|
SW_SHOWMINNOACTIVE
|
窗口最小化,激活窗口仍然维持激活状态。
|
SW_SHOWNA
|
以窗口原来的状态显示窗口。激活窗口仍然维持激活状态。
|
SW_SHOWNOACTIVATE
|
以窗口最近一次的大小和状态显示窗口。激活窗口仍然维持激活状态。
|
SW_SHOWNORMAL
|
激活并显示一个窗口。如果窗口被最小化或最大化,系统将其恢复到原来的尺寸和大小。应用程序在第一次显示窗口的时候应该指定此标志。
|
7. 更新窗口
如果窗口更新的区域不为空,UpdateWindow函数通过发送一个WM_PAINT消息来更新指定窗口的客户区。函数绕过应用程序的消息队列,直接发送WM_PAINT消息给指定窗口的窗口过程,如果更新区域为空,则不发送消息。
8. 消息循环
- MSG msg;
- while (GetMessage(&msg,NULL,0,0))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
8.1. MSG 结构体
MSG结构体包含一条WindowMessage的全部信息
- typedef struct tagMSG {
- HWND hwnd;
- UINT message;
- WPARAM wParam;
- LPARAM lParam;
- DWORD time;
- POINT pt;
- }MSG;
8.2. 自定义MSG
参见博文:MFC程序最小化到系统托盘区的一个简单实例
9. 窗口过程
窗口过程函数是一个应用程序定义的函数,用来处理发送到窗口的消息。WNDPROC类型定义了一个指向该回调函数的指针。WindowProc是用于应用程序定义函数的占位符,也就是说,程序员自己更改WindowProc这个名称,但是参数类型不变。
一个Windows 程序可以包含多个窗口过程。一个窗口过程总是与调用RegisterClass注册的特定窗口类相关联。程序通常不直接调用窗口过程。窗口过程通常由 Windows 本身调用。通过调用 SendMessage 函数,程序能够直接调用它自己的窗口过程。
9.1. 函数声明
- LRESULT CALLBACK WindowProc(
- HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam
- );
9.2. 函数功能
该函数主要是用来处理发送给窗口的各类MSG消息。
窗口过程在处理消息时,必须返回0。
窗口过程不予处理的所有消息应该被传给名为DefWindowProc() 函数。
从 DefWindowProc 返回的值必须由窗口过程返回。
本文部分内容来自MSDN和网络。
转载请注明地址: