12 Windows编程——子窗口和系统内置窗口类“BUTTON”
创建子窗口类,使得子窗口有自己的处理过程。
子窗口类型WS_CHILD不能和WS_POPUP一起使用!
为什么子窗口要有自己的处理过程?
如果使用主窗口类来创建子窗口,那么子窗口和主窗口将公用窗口处理过程,此时,窗口处理过程在进行消息处理的时候,必须判断是哪个窗口的消息,非常不方便。
子窗口必须有自己的窗口类型WSCHILD,并且子窗口的父窗口句柄一定不能使NULL,子窗口的坐标主窗口的映射方式和客户区有关。否则CreateWindow函数就会失败。
客户定制消息:WL_USER+N,其中N可以是0x7FFF-WM_USER之间的任何值。发送窗口消息的函数:
SendMessage
LRESULT WINAPI SendMessage(
_In_ HWND hWnd,
_In_ UINT Msg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
将指定的消息发送到一个或多个窗口。此函数为指定的窗口调用窗口程序,直到窗口程序处理完消息再返回。和函数PostMessage不同,PostMessage是将一个消息寄送到一个线程的消息队列后就立即返回。
hWnd: 发送消息的目标窗口;
Msg: WMXXX消息;
wParam: 用户自定义的一个32位值;
1param: 用户自定义的一个32为值;
COLORREF SetBkColor( HDC hdc, COLORREF color );
用指定的颜色值来设置当前的背景色,如果指定的颜色值超出了当前设备的表示范围,则设置为最近似的、设备可以表示的颜色。
改变窗口位置
BOOL WINAPI SetWindowPos( _In_ HWND hWnd, _In_opt_ HWND hWndInsertAfter, _In_ int X, _In_ int Y, _In_ int cx, _In_ int cy, _In_ UINT uFlags );
-
-
HWND_BOTTOM:值为1,将窗口置于Z序的底部。如果参数hWnd标识了一个顶层窗口,则窗口失去顶级位置,并且被置在其他窗口的底部。
-
HWND_NOTOPMOST:值为-2,将窗口置于所有非顶层窗口之上(即在所有顶层窗口之后)。如果窗口已经是非顶层窗口则该标志不起作用。
-
HWND_TOP:值为0,将窗口置于Z序的顶部。
-
HWND_TOPMOST:值为-1,将窗口置于所有非顶层窗口之上。即使窗口未被激活窗口也将保持顶级位置。
-
X:以客户坐标指定窗口新位置的左边界。
Y:以客户坐标指定窗口新位置的顶边界。
cx:以像素指定窗口的新的宽度。
cy:以像素指定窗口的新的高度。
uFlags:窗口尺寸和定位的标志。
改变指定窗口的属性
LONG WINAPI SetWindowLong( _In_ HWND hWnd, _In_ int nIndex, _In_ LONG dwNewLong );
hwnd: 窗口句柄;
nIndex: 要改变窗口的那个参数;
dwNewLong: 窗口参数的新值;
获取窗口类信息
BOOL WINAPI GetClassInfo(
_In_opt_ HINSTANCE hInstance,
_In_ LPCTSTR lpClassName,
_Out_ LPWNDCLASS lpWndClass
);
hInstance: 当前程序的基地址,也就是程序的句柄;
1pclassName: 类名;
1pwndclass: 指向 WNDCLASS类型的指针;
画矩形
BOOL Rectangle( HDC hdc, int left, int top, int right, int bottom );
画一个矩形,可以用当前的画笔画矩形轮廓,用当前画刷进行填充。
获得当前程序基地址,或者HINSTANCE的函数:GetModuleHandle(NULL);
系统内置的窗口类型“BUTTON”
WL_COMMAND消息:
wParam:
lparam:
不使用子窗口类创建一个按钮,点击按钮按钮会变色,源码
1 //#define _AFXDLL 2 //#include<afx.h> 3 #include<Windows.h> 4 #include<tchar.h> 5 6 #ifndef _AFXDELL 7 #define TRACE(a,b) 8 #endif 9 10 LRESULT CALLBACK WindProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 11 12 int WinMain(HINSTANCE hInst, HINSTANCE tmp, LPSTR szCmd, int nShow) 13 { 14 WNDCLASS WndClass; 15 TCHAR* ClassName = TEXT("MyClass"); 16 HWND hwnd; 17 MSG msg; 18 HBRUSH hBrush; 19 20 hBrush = CreateSolidBrush(RGB(85,85,16)); 21 WndClass.cbClsExtra = 0; 22 WndClass.cbWndExtra = 0; 23 WndClass.hbrBackground = hBrush; 24 WndClass.hCursor = LoadCursor(NULL, IDC_ARROW); 25 WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); 26 WndClass.hInstance = hInst; 27 WndClass.lpfnWndProc = WindProc; 28 WndClass.lpszClassName = ClassName; 29 WndClass.lpszMenuName = NULL; 30 WndClass.style = CS_VREDRAW | CS_HREDRAW; 31 32 RegisterClass(&WndClass); 33 hwnd = CreateWindow(ClassName, TEXT("Hello"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 500, 300, NULL, NULL, hInst, NULL); 34 ShowWindow(hwnd, nShow); 35 UpdateWindow(hwnd); 36 37 while (GetMessage(&msg, NULL, 0, 0)) 38 { 39 TranslateMessage(&msg); 40 DispatchMessage(&msg); 41 } 42 return 0; 43 } 44 LRESULT CALLBACK WindProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 45 { 46 HDC hdc; 47 PAINTSTRUCT pt; 48 HBRUSH hBrush; 49 static int status; 50 switch (message) 51 { 52 case WM_CREATE: 53 return 0; 54 case WM_SIZE: 55 return 0; 56 case WM_PAINT: 57 hdc = BeginPaint(hwnd, &pt); 58 if(status == 0) 59 { 60 hBrush = CreateSolidBrush(RGB(200, 200, 200)); 61 SelectObject(hdc, hBrush); 62 Rectangle(hdc, 200, 100, 300, 125); 63 SetBkColor(hdc, RGB(200, 200, 200)); 64 TextOut(hdc, 240, 108, TEXT("OK"), 2); 65 TextOut(hdc, 0, 0, TEXT("Hit me!"), 7); 66 } 67 else 68 { 69 hBrush = CreateSolidBrush(RGB(0, 200, 200)); 70 SelectObject(hdc, hBrush); 71 Rectangle(hdc, 200, 100, 300, 125); 72 SetBkColor(hdc, RGB(0, 200, 200)); 73 TextOut(hdc, 240, 108, TEXT("OK"), 2); 74 TextOut(hdc, 0, 0, TEXT("Hit me!"), 7); 75 } 76 EndPaint(hwnd, &pt); 77 return 0; 78 case WM_LBUTTONDOWN: 79 if (LOWORD(lParam)>200 && LOWORD(lParam)<300 && HIWORD(lParam)<125 && HIWORD(lParam)>100) 80 { 81 status = 1; 82 InvalidateRect(hwnd, NULL,TRUE); 83 } 84 return 0; 85 case WM_LBUTTONUP: 86 InvalidateRect(hwnd, NULL,TRUE); 87 status = 0; 88 return 0; 89 case WM_DESTROY: 90 PostQuitMessage(0); 91 return 0; 92 default: 93 break; 94 } 95 96 return DefWindowProc(hwnd, message, wParam, lParam); 97 }
使用子窗口创建按钮
1 1.h 2 //#pragma once 3 //#define _AFXDLL 4 //#include<afx.h> 5 #include<Windows.h> 6 #include<tchar.h> 7 8 #ifndef _AFXDELL 9 #define TRACE(a,b) 10 #endif 11 12 HWND CreateChild(HWND ParentHwnd, int x, int y, int cx, int cy); 13 extern HINSTANCE G_hInst;
1 1.c 2 #include"1.h" 3 HINSTANCE G_hInst; 4 LRESULT CALLBACK WindProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 5 6 int WinMain(HINSTANCE hInst, HINSTANCE tmp, LPSTR szCmd, int nShow) 7 { 8 WNDCLASS WndClass; 9 TCHAR* ClassName = TEXT("MyClass"); 10 HWND hwnd; 11 MSG msg; 12 HBRUSH hBrush; 13 14 hBrush = CreateSolidBrush(RGB(85,85,16)); 15 G_hInst = hInst; 16 WndClass.cbClsExtra = 0; 17 WndClass.cbWndExtra = 0; 18 WndClass.hbrBackground = hBrush; 19 WndClass.hCursor = LoadCursor(NULL, IDC_ARROW); 20 WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); 21 WndClass.hInstance = hInst; 22 WndClass.lpfnWndProc = WindProc; 23 WndClass.lpszClassName = ClassName; 24 WndClass.lpszMenuName = NULL; 25 WndClass.style = CS_VREDRAW | CS_HREDRAW; 26 27 RegisterClass(&WndClass); 28 hwnd = CreateWindow(ClassName, TEXT("Hello"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 500, 300, NULL, NULL, hInst, NULL); 29 ShowWindow(hwnd, nShow); 30 UpdateWindow(hwnd); 31 32 while (GetMessage(&msg, NULL, 0, 0)) 33 { 34 TranslateMessage(&msg); 35 DispatchMessage(&msg); 36 } 37 return 0; 38 } 39 LRESULT CALLBACK WindProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 40 { 41 HDC hdc; 42 PAINTSTRUCT pt; 43 HBRUSH hBrush; 44 static int status; 45 static HWND child1,child2,child3; 46 TCHAR buf[1024]; 47 switch (message) 48 { 49 case WM_CREATE: 50 child1 = CreateChild(hwnd, 200, 100, 100, 25); 51 child2 = CreateChild(hwnd, 200, 150, 100, 25); 52 child3 = CreateChild(hwnd, 200, 200, 100, 25); 53 return 0; 54 case WM_SIZE: 55 return 0; 56 case WM_PAINT: 57 hdc = BeginPaint(hwnd, &pt); 58 EndPaint(hwnd, &pt); 59 return 0; 60 case WM_USER+1: 61 hdc = GetDC(hwnd); 62 if((LPARAM)child1==lParam) 63 { 64 TextOut(hdc,0,0,TEXT("Hit First button"),16); 65 } 66 if((LPARAM)child2==lParam) 67 { 68 TextOut(hdc,0,0,TEXT("Hit Second button"),17); 69 } 70 if((LPARAM)child3==lParam) 71 { 72 TextOut(hdc,0,0,TEXT("Hit Third button"),16); 73 } 74 ReleaseDC(hwnd, hdc); 75 ValidateRect(hwnd, NULL); 76 return 0; 77 case WM_USER + 2: 78 InvalidateRect(hwnd, NULL, TRUE); 79 return 0; 80 case WM_DESTROY: 81 PostQuitMessage(0); 82 return 0; 83 default: 84 break; 85 } 86 87 return DefWindowProc(hwnd, message, wParam, lParam); 88 }
1 2.c 2 #include"1.h" 3 extern HINSTANCE G_hInst; 4 static LRESULT CALLBACK WindProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 5 6 HWND CreateChild(HWND ParentHwnd, int x, int y, int cx, int cy) 7 { 8 WNDCLASS WndClass,MyWnd; 9 TCHAR* ClassName = TEXT("MyChild"); 10 HWND hwnd; 11 MSG msg; 12 HBRUSH hBrush; 13 14 hBrush = CreateSolidBrush(RGB(200, 200, 200)); 15 WndClass.cbClsExtra = 0; 16 WndClass.cbWndExtra = 0; 17 WndClass.hbrBackground = hBrush; 18 WndClass.hCursor = LoadCursor(NULL, IDC_ARROW); 19 WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); 20 WndClass.hInstance = G_hInst; 21 WndClass.lpfnWndProc = WindProc; 22 WndClass.lpszClassName = ClassName; 23 WndClass.lpszMenuName = NULL; 24 WndClass.style = CS_VREDRAW | CS_HREDRAW; 25 26 if (!GetClassInfo(G_hInst,ClassName,&MyWnd)) 27 { 28 RegisterClass(&WndClass); 29 } 30 31 hwnd = CreateWindow(ClassName, TEXT("OK"), WS_CHILD, x, y, cx, cy, ParentHwnd, NULL, G_hInst, NULL); 32 ShowWindow(hwnd, SW_SHOW); 33 UpdateWindow(hwnd); 34 35 //GetMessage第二个参数为NULL时,会获取所有消息。因为父窗口已经获取消息了,所以没必要再获取了 36 /*while (GetMessage(&msg, NULL, 0, 0)) 37 { 38 TranslateMessage(&msg); 39 DispatchMessage(&msg); 40 }*/ 41 return hwnd; 42 } 43 44 LRESULT CALLBACK WindProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 45 { 46 HDC hdc; 47 PAINTSTRUCT pt; 48 HBRUSH hBrush; 49 static int status; 50 static int cx,cy; 51 52 switch (message) 53 { 54 case WM_CREATE: 55 return 0; 56 case WM_SIZE: 57 cx=LOWORD(lParam); 58 cy=HIWORD(lParam); 59 return 0; 60 case WM_PAINT: 61 hdc = BeginPaint(hwnd, &pt); 62 //TRACE(TEXT("status=%d\n"),status); 63 if (status == 0) 64 { 65 hBrush = CreateSolidBrush(RGB(200, 200, 200)); 66 SelectObject(hdc, hBrush); 67 Rectangle(hdc, 0, 0, cx,cy); 68 SetBkColor(hdc, RGB(200, 200, 200)); 69 TextOut(hdc, 40,5, TEXT("OK"), 2); 70 } 71 else 72 { 73 hBrush = CreateSolidBrush(RGB(0, 200, 200)); 74 SelectObject(hdc, hBrush); 75 Rectangle(hdc, 0, 0, cx,cy); 76 SetBkColor(hdc, RGB(0, 200, 200)); 77 TextOut(hdc, 40,5, TEXT("OK"), 2); 78 } 79 EndPaint(hwnd, &pt); 80 return 0; 81 case WM_LBUTTONDOWN: 82 { 83 status = 1; 84 InvalidateRect(hwnd, NULL, TRUE); 85 SendMessage(hwnd,WM_PAINT,NULL,NULL); 86 SendMessage(GetParent(hwnd), WM_USER + 1, NULL,(LPARAM)hwnd); 87 88 } 89 return 0; 90 case WM_LBUTTONUP: 91 status = 0; 92 InvalidateRect(hwnd, NULL, TRUE); 93 SendMessage(GetParent(hwnd), WM_USER + 2, NULL,NULL); 94 return 0; 95 case WM_DESTROY: 96 PostQuitMessage(0); 97 return 0; 98 default: 99 break; 100 } 101 102 return DefWindowProc(hwnd, message, wParam, lParam); 103 }
还可以使用WIndows自身的button控件
1 #include<Windows.h> 2 #include<Windowsx.h> 3 4 LRESULT CALLBACK WindProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 5 6 int WinMain(HINSTANCE hInst, HINSTANCE tmp, LPSTR szCmd, int nShow) 7 { 8 WNDCLASS WndClass; 9 TCHAR* ClassName = TEXT("MyClass"); 10 HWND hwnd; 11 MSG msg; 12 13 WndClass.cbClsExtra = 0; 14 WndClass.cbWndExtra = 0; 15 WndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); 16 WndClass.hCursor = LoadCursor(NULL, IDC_ARROW); 17 WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); 18 WndClass.hInstance = hInst; 19 WndClass.lpfnWndProc = WindProc; 20 WndClass.lpszClassName = ClassName; 21 WndClass.lpszMenuName = NULL; 22 WndClass.style = CS_VREDRAW | CS_HREDRAW; 23 24 if (!RegisterClass(&WndClass)) 25 { 26 MessageBox(NULL, TEXT("Gegister Class Fail!!"), TEXT("error"), MB_OK); 27 return 0; 28 } 29 30 hwnd = CreateWindow(ClassName, TEXT("Hello"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 500, 300, NULL, NULL, hInst, NULL); 31 if (hwnd == NULL) 32 { 33 MessageBox(NULL, TEXT("Create Window Fail!!"), TEXT("error"), MB_OK); 34 return 0; 35 } 36 ShowWindow(hwnd, nShow); 37 UpdateWindow(hwnd); 38 39 while (GetMessage(&msg, NULL, 0, 0)) 40 { 41 TranslateMessage(&msg); 42 DispatchMessage(&msg); 43 } 44 45 return 0; 46 } 47 48 LRESULT CALLBACK WindProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 49 { 50 HDC hdc; 51 static HWND button; 52 switch (message) 53 { 54 case WM_CREATE: 55 button = CreateWindow(TEXT("button"), TEXT("OK"), WS_CHILD | WS_VISIBLE, 150, 50, 100, 25, hwnd, NULL, GetModuleHandle(NULL), NULL); 56 //禁用按钮,按钮变灰色 57 //Button_Enable(button, FALSE); 58 Button_SetText(button,TEXT("测试")); 59 return 0; 60 case WM_COMMAND: 61 hdc = GetDC(hwnd); 62 if (button == (HWND)lParam) 63 { 64 TextOut(hdc, 0, 0, TEXT("Hit Button"), 10); 65 } 66 if (BN_CLICKED == HIWORD(wParam)) //测试控件通知码 67 { 68 TextOut(hdc, 0, 30, TEXT("BN_CLICKED Hit Button"), 21); 69 } 70 ReleaseDC(hwnd, hdc); 71 ValidateRect(hwnd, NULL); 72 case WM_DESTROY: 73 PostQuitMessage(0); 74 return 0; 75 default: 76 break; 77 } 78 79 return DefWindowProc(hwnd, message, wParam, lParam); 80 }
HIWORD(wParam)控件通知码
LOWORD(wParam)控件标识
lParam控件的窗口句柄