控件
控件是什么?
控件一般指的是按钮、输入框、静态框、树形框以及分层框。
那按钮怎么创建呢?
按钮也是一种窗口,所以呢,也可以用CreateWindowEx来创建。
CreateWindowEx(
WS_EX_CLIENTEDGE,
"Button", //既然是按钮,它的类名就是Button,所以大家以后创建窗口时千万不要和这个冲突了哦,另外,会引发冲突的,还有Static静态框,Edit输入框、编辑框等等
"blalala", //这个就是按钮上面的字符串
/*
+---------+
|blablabla|
+---------+
*/
...
所以呢,大家可以发现按钮的创建十分简单,但是既然Windows是关于消息的,那么就一定需要按钮的响应消息,这个嘛,也不难,不过大家不要急于求成,我们先把按钮给显示出来吧。
#include <windows.h>
LRESULT CALLBACK WndProc(HWND hwnd, //是哪个窗口发来的消息。
UINT Message, //消息是什么?
WPARAM wParam, //附加的消息
LPARAM lParam)//附加的消息2
{
switch(Message)
{
case WM_CREATE: //这个就是窗口的初始化消息
{
//我们就是要在初始化里面来放置按钮
CreateWindowEx(WS_EX_CLIENTEDGE,//EX窗口风格
"Button",//窗口类名,在头文件中已经帮你封装好了
"blablabla", //这就是写文字的地方
WS_VISIBLE|WS_CHILD, //照样是初始可见的,至于为什么没有WS_OVERLAPPEDWINDOW是因为他不需要最小化框,最大化框,以及其他的设置,要提一点,如果你不想要一些设置,可以使用这样的运算&~<你不要的风格>,其次就是WS_CHILD了,它的意思是这一个窗口将会作为别人的子窗口,切记,在控件中一定要带上它!
0,0, //左上角的坐标
100,20, //宽度和高度
hwnd, //这是父窗口句柄,要是填NULL的话,它就不会生成,所以这个也是务必要填的。
NULL, //这个地方暂时填入NULL,但是这个地方也是极其重要的,它就是按钮被按下时发送的消息
((LPCREATESTRUCT)->hInstance)/*hInstance*/, //这个就是应用程序实例句柄
NULL);//就这样做完了,诶,等等好像有个地方有问题,hInstance未定义!!!可是怎么办呢?🤔
//可以做一个全局变量来保存应用程序实例句柄,但是也可以这样做((LPCREATESTRUCT)->hInstance)
}
default:
{
return DefWindowProc(hwnd,Message,wParam,lParam);
}
}
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
WNDCLASSEX wc;//一个窗口类
HWND hwnd;//还记得这个是什么吗?对,就是窗口句柄
MSG Msg;//消息
memset(&wc,0,sizeof(wc));
wc.cbSize = sizeof(WNDCLASSEX);
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;//他要你传一个应用程序实例句柄
wc.hCursor = LoadCursor(NULL, IDC_ARROW);//他说要个鼠标句柄
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);//请告诉它窗口的颜色,可以不要加1,也可以加2、加3都可以
wc.lpszClassName = "WindowClass";//窗口类名,注意不是窗口标题、窗口名
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); //他说他要一个图标
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); //emm...这个就跟上面的填一样的
/*
LoadIcon会传回一个图标句柄
LoadCursor会传回一个鼠标句柄
*/
if(!RegisterClassEx(&wc)) {
MessageBox(NULL, "Window Registration Failed!","Error!",MB_ICONEXCLAMATION|MB_OK);
return 0;
}//注册窗口,如果注册失败,则弹出对话框
hwnd = CreateWindowEx(WS_EX_CLIENTEDGE,//EX窗口风格
"WindowClass",//刚才所说的窗口类名
"Caption",//这个就是窗口标题啦
WS_VISIBLE|WS_OVERLAPPEDWINDOW,//普通窗口风格,WS_VISIBLE它指的是窗口初始是否可见;WS_OVERLAPPEDWINDOW指的是一般窗口风格,剧透一下,将来的控件窗口就不需要了。
CW_USEDEFAULT,CW_USEDEFAULT,//窗口左上角的xy坐标
640,480,//窗口的宽和高,不知道为什么它不是长和宽,而是宽和高(长)
NULL,//这个是个窗口句柄,NULL为桌面
NULL,//HMENU昨天忘记讲了,它不仅代表了一个菜单,还是一个窗口标识,将来控件会用到
hInstance,//填空题:HINSTANCE代表了_____,答案:应用程序实例句柄
NULL);//附加参数(没什么卵用)
if(hwnd == NULL) {
MessageBox(NULL, "Window Creation Failed!","Error!",MB_ICONEXCLAMATION|MB_OK);
return 0;
}//与上面一样,窗口创建失败则弹出一个对话框
while(GetMessage(&Msg, NULL, 0, 0) > 0){//获取消息Get得到
TranslateMessage(&Msg);//翻译消息,甭管它是什么,照做就行
DispatchMessage(&Msg);//与上面同理,要真有兴趣可以一搜
}//~~这就是我们传说中的消息循环~~
return Msg.wParam;
}
好了,把应用程序实例句柄的问题解决了,这个文件就可以编译通过了,上面会有一个按钮,显示着blablabla,虽然按它没有反应,但是我当然会让他有反应的…
好,我们现在就在刚才说的CreateWindowEx的第十个参数里面填入(HMENU)1,至于这个数字,你想填几就填几,也可以用define,不过一定要记住它,然后我们便要在switch里面加上这样一段
case WM_COMMAND: //这个消息是表示有系统消息响应的消息
{
switch(LOWORD(wParam))//取wParam的低位字节,里面有之前的第十个参数
{
case 1: //这里我就拿1做例子,反正就是你填的那个数
{
//就在这个里面加入响应代码
//比方说我给他弹出来一个小小的对话框,对,就是第一篇里面的MessageBox,其实MessageBox他有很大的用处,就跟我们还不会调试的时候,使用printf来测试数据一般,所以MessageBox还是一个很好的东西,千万不要因为它基础而忘掉了它
MessageBox(.../*我就先送到这里了,你可以自己填入一些,也可以回去查阅下资料,再来填*/);
}
}
}
插入了这个代码片段之后,我们的按钮,你一按就会有一个对话框给弹出来,上面写着一些东西,是不是非常的高兴呢✌?作者也为你们高兴😊😊😊(看他笑得多开心啊!)
今天就到这里了,如果还有问题,请私信