实现的效果就是在主窗口客户区动态创建一个按钮,然后单击按钮时弹出一个消息框。这就是按钮单击响应了,这里表示这个按钮并不是摆设哦。当窗口大小改变的时候,按钮的位置会随着改变位置哦。用Win32实现这个效果,其实也是挺激动的哈。
先看看下面的效果截图:
【Win32创建按钮并让按钮随着窗口大小改变而改变位置,并且可以响应按钮单击事件】
那么我们先要用CreateWindow函数创建一个按钮,我们要创建一个按钮,所以就在第一个参数中传入了“Button”窗口类来创建按钮。实际上这个就是一个按钮控件咯。然后我将按钮的标题设置为了“【C++技术网http://www.cjjjs.com】”。而在第三个参数时,指定了WS_CHILD|WS_VISIBLE风格的组合,前面表示此按钮时主窗口的子窗口,第二个让按钮创建后就可以看到。如此,按钮就可以创建出来贴在客户区了。然而如何确定大小呢?当然你可以直接填入起始坐标和宽高值,而我用GetClientRect获取了客户区的大小,然后将按钮的起点设置为了客户区的中间点,即(rect.right/2,rect.bottom/2)。宽高都是100。然而这个效果其实在最终你是看不到的。因为在显示主窗口的时候,会产生WM_SIZE的主窗口大小调整的消息。而我们在这里需要让按钮随时跟着主窗口的大小变化而调整位置。而此时的效果会掩盖创建时指定的按钮位置和宽高。
然后在第八个参数中,我们设置了父窗口的句柄,这样建立了按钮和主窗口的父子关系。因为按钮本身就是要作为主窗口的子窗口而存在的,所以有这个父子关系后,按钮才能贴在主窗口的客户区哦。如果不设置,自然就达不到这个效果咯。
在主窗口的WM_SIZE消息中,我们还是使用GetClientRect获取了客户区的大小,然后使用MoveWindow函数将按钮的位置移动到客户区的水平方向的从左向右方向的四分之一处,垂直方向的中间开始,大小则调整为300x100(宽高)。将最后一个参数设置为FALSE,即不重绘按钮。
那么这样按钮位置和大小随着窗口的大小改变而改变的功能就实现了,就这么简单。而响应客户区创建的按钮,如何做?
因为习惯了MFC,我就在想,这个按钮如何弄一个ID呢?想不出来,但是我知道,按钮子控件的消息,是以WM_COMMAND消息传递给主窗口来处理的。所以我在MSDN输入WM_COMMAND查询消息各个参数的含义。看到解释瞬间明白了。Win32就是简单直白。没有所谓的控件ID之说,那是MFC搞的一套东西。只要你有窗口句柄就可以了
所以在主窗口的WM_COMMAND消息下判断消息所属的窗口句柄即可。这个消息的lParam参数就是控件(子窗口)的窗口句柄。所以,我们只需要将这个参数与按钮的窗口句柄比较即可。当然,lParam参数类型和HWND类型不一致,记得转换一下。所以在if里面输出一个消息框即可。
大功告成,下面是完整代码:
#include "windows.h"
#include <tchar.h>
// - 项目是Unicode字符集
LRESULT CALLBACK WinProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
TCHAR Info[100]=_T("【C++技术网http://www.cjjjs.com】");
RECT rect;
static HWND hChild=NULL;
switch (message)
{
case WM_CREATE:
GetClientRect(hwnd,&rect);
hChild = CreateWindow(_T("Button"),Info,WS_CHILD|WS_VISIBLE,rect.right/2,rect.bottom/2,100,100,hwnd ,NULL,NULL,NULL);
return 0;
case WM_COMMAND:
if ((HWND)lParam==hChild)
{
MessageBox(hwnd,Info,Info,MB_OK);
}
return 0;
case WM_PAINT:
{
hdc = BeginPaint(hwnd,&ps);
EndPaint(hwnd,&ps);
}
return 0;
case WM_SIZE:
GetClientRect(hwnd,&rect);
MoveWindow(hChild,rect.right/4,rect.bottom/2,300,100,FALSE);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
}
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrev,LPSTR lpCmd,int iShow)
{
TCHAR ClassName[] = _T("MyClass");
TCHAR title1[] = _T("C++技术网http://www.cjjjs.com");
WNDCLASS wndClass;
wndClass.cbClsExtra=0;
wndClass.cbWndExtra=0;
wndClass.hbrBackground= (HBRUSH)GetStockObject(LTGRAY_BRUSH);
wndClass.hCursor=LoadCursor(NULL,IDC_ARROW);
wndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
wndClass.hInstance = hInstance;
wndClass.lpfnWndProc = WinProc;
wndClass.lpszClassName = ClassName;
wndClass.lpszMenuName=NULL;
wndClass.style=CS_HREDRAW|CS_VREDRAW;
if(!RegisterClass(&wndClass)) return 0;
HWND hwnd = CreateWindow(ClassName,title1,WS_OVERLAPPEDWINDOW,0,0,600,500,NULL,NULL,hInstance,NULL);
ShowWindow(hwnd,SW_SHOWNORMAL);
MSG msg;
while (GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}