如何创建一个win32程序
2015-11-13 14:25
639 查看
学过一段时间的c++,建立的都是win32 console application,我来介绍一下如何建立一个简单的win32程序,相比win32 console application,会有大家常见的窗口,更像程序一些。
首先要写类似于main函数的WinMain,
int WINAPI WinMain( HINSTANCE hinstance,
HINSTANCE hprevinstance,
LPSTR lpcmdline,
int ncmdshow)
WINAPI是干什么的呢?它是调用声明,相当于_stdcal。c++默认的调用声明是_cdecl。两者区别为:
_stdcal函数在结束后自己清栈,_cdecl由调用者(不是指人自己,指的是调用的程序)清栈。当函数参数个数可变的时候,只能_cdecl调用,在不知道个数的情况下,函数自己不知道怎么清栈;不同的编译器会按不同的方式堆栈,这样会使得如果使用_cdecl声明时,调用者不一定可以成功清栈。
(参考了http://blog.csdn.net/dengziliang001/article/details/17448789)
hinstance是Windows为应用程序产生的实例句柄,可以看成这个就是程序的地址,跟踪程序。
hprevinstance,现在已经不使用这个参数了。
lpcmdline,与main中的命令行差不多,基本写程序时不用管。
ncmdshow,带有如何打开主应用程序窗口的信息,比如最大化,最小化,一般用的多的是ShowWindow(),ncmd不怎么用。
函数体怎么写呢?看看下面:
WNDCLASSEX winclass; // this will hold the class we create
HWND hwnd;// generic window handle
MSG msg;// generic message
HDC hdc; // graphics device context
// first fill in the window class stucture
winclass.cbSize = sizeof(WNDCLASSEX);
winclass.style = CS_DBLCLKS | CS_OWNDC |
CS_HREDRAW | CS_VREDRAW;
winclass.lpfnWndProc = WindowProc;
winclass.cbClsExtra = 0;
winclass.cbWndExtra = 0;
winclass.hInstance = hinstance;
winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
winclass.hCursor = LoadCursor(NULL, IDC_ARROW);
winclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
winclass.lpszMenuName = NULL;
winclass.lpszClassName = WINDOW_CLASS_NAME;
winclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
WNDCLASSEX是一个类,因为你要创建一个窗口,然后在上面输入输出操作,WNDCLSSEX可以看成一个窗口类,而winclass可以看成实例(即变量),hwnd,msg,hdc在后面会讲到,首先要做的是填winclass的各个属性,后面的一大串全是设置属性,比较重要的是 winclass.style,它指出了窗口的重要属性,如窗口宽度变化后会重画,高度变化后会重画,剩下的参数查msdn就知道了。
然后你需要去注册这个类,
if (!RegisterClassEx(&winclass))
return(0);
外面的if,当没注册成功就返回0,防止程序没注册成功,往下运行出现未知的错误。
然后就是创建一个窗口,
if (!(hwnd = CreateWindowEx(NULL, // extended style
WINDOW_CLASS_NAME, // class
"Demo", // title
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
0,0, // initial x,y
500,400, // initial width, height
NULL,
// handle to parent
NULL,
// handle to menu
hinstance,// instance of this application
NULL)))
// extra creation parms
return(0);
CreateWindowEx()会返回一个指向窗口的的句柄,相当于它的地址。
上面的一系列都可以直接复制张贴,根据需要,改一改属性即可,然后我一般会编一个循环,去处理消息。
while(TRUE)
{
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
} // end if
} // end while
return(msg.wParam);
}
其中 if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
理解成先判断有没有消息,有的话就传递给相应的程序处理,消息可以使单击鼠标左键,关闭窗口等。
之后return,就写好主函数。
除了主函数还需要写一个消息处理函数,每个窗口都有一个窗口处理函数,而关联两者,就是在设置窗口属性时的winclass.lpfnWndProc= WindowProc,WindowProc是处理函数的名字,当窗口有相应的消息的时候,就会调用处理函数处理.下面是一个窗口处理函数:
LRESULT CALLBACK WindowProc(HWND hwnd,
UINT msg,
WPARAM wparam,
LPARAM lparam)
{
PAINTSTRUCT ps;
switch(msg){
case WM_CREATE:
{
} break;
case WM_PAINT:
{
BeginPaint(hwnd,&ps);
EndPaint(hwnd,&ps);
return(0);
} break;
case WM_DESTROY:
{
PostQuitMessage(0);
return(0);
} break;
default:break;
}
return (DefWindowProc(hwnd, msg, wparam, lparam));
}
首先看一下函数的参数,hwnd 是调用窗口的句柄,便于对窗口操作,msg有消息类型的信息,wparam,lparam包含具体消息的细节。
总之其实上面的都可以直接复制张贴,至于该怎么操作只需要改一下处理函数,还有在while循环里做些填充。
首先要写类似于main函数的WinMain,
int WINAPI WinMain( HINSTANCE hinstance,
HINSTANCE hprevinstance,
LPSTR lpcmdline,
int ncmdshow)
WINAPI是干什么的呢?它是调用声明,相当于_stdcal。c++默认的调用声明是_cdecl。两者区别为:
_stdcal函数在结束后自己清栈,_cdecl由调用者(不是指人自己,指的是调用的程序)清栈。当函数参数个数可变的时候,只能_cdecl调用,在不知道个数的情况下,函数自己不知道怎么清栈;不同的编译器会按不同的方式堆栈,这样会使得如果使用_cdecl声明时,调用者不一定可以成功清栈。
(参考了http://blog.csdn.net/dengziliang001/article/details/17448789)
hinstance是Windows为应用程序产生的实例句柄,可以看成这个就是程序的地址,跟踪程序。
hprevinstance,现在已经不使用这个参数了。
lpcmdline,与main中的命令行差不多,基本写程序时不用管。
ncmdshow,带有如何打开主应用程序窗口的信息,比如最大化,最小化,一般用的多的是ShowWindow(),ncmd不怎么用。
函数体怎么写呢?看看下面:
WNDCLASSEX winclass; // this will hold the class we create
HWND hwnd;// generic window handle
MSG msg;// generic message
HDC hdc; // graphics device context
// first fill in the window class stucture
winclass.cbSize = sizeof(WNDCLASSEX);
winclass.style = CS_DBLCLKS | CS_OWNDC |
CS_HREDRAW | CS_VREDRAW;
winclass.lpfnWndProc = WindowProc;
winclass.cbClsExtra = 0;
winclass.cbWndExtra = 0;
winclass.hInstance = hinstance;
winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
winclass.hCursor = LoadCursor(NULL, IDC_ARROW);
winclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
winclass.lpszMenuName = NULL;
winclass.lpszClassName = WINDOW_CLASS_NAME;
winclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
WNDCLASSEX是一个类,因为你要创建一个窗口,然后在上面输入输出操作,WNDCLSSEX可以看成一个窗口类,而winclass可以看成实例(即变量),hwnd,msg,hdc在后面会讲到,首先要做的是填winclass的各个属性,后面的一大串全是设置属性,比较重要的是 winclass.style,它指出了窗口的重要属性,如窗口宽度变化后会重画,高度变化后会重画,剩下的参数查msdn就知道了。
然后你需要去注册这个类,
if (!RegisterClassEx(&winclass))
return(0);
外面的if,当没注册成功就返回0,防止程序没注册成功,往下运行出现未知的错误。
然后就是创建一个窗口,
if (!(hwnd = CreateWindowEx(NULL, // extended style
WINDOW_CLASS_NAME, // class
"Demo", // title
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
0,0, // initial x,y
500,400, // initial width, height
NULL,
// handle to parent
NULL,
// handle to menu
hinstance,// instance of this application
NULL)))
// extra creation parms
return(0);
CreateWindowEx()会返回一个指向窗口的的句柄,相当于它的地址。
上面的一系列都可以直接复制张贴,根据需要,改一改属性即可,然后我一般会编一个循环,去处理消息。
while(TRUE)
{
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
} // end if
} // end while
return(msg.wParam);
}
其中 if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
理解成先判断有没有消息,有的话就传递给相应的程序处理,消息可以使单击鼠标左键,关闭窗口等。
之后return,就写好主函数。
除了主函数还需要写一个消息处理函数,每个窗口都有一个窗口处理函数,而关联两者,就是在设置窗口属性时的winclass.lpfnWndProc= WindowProc,WindowProc是处理函数的名字,当窗口有相应的消息的时候,就会调用处理函数处理.下面是一个窗口处理函数:
LRESULT CALLBACK WindowProc(HWND hwnd,
UINT msg,
WPARAM wparam,
LPARAM lparam)
{
PAINTSTRUCT ps;
switch(msg){
case WM_CREATE:
{
} break;
case WM_PAINT:
{
BeginPaint(hwnd,&ps);
EndPaint(hwnd,&ps);
return(0);
} break;
case WM_DESTROY:
{
PostQuitMessage(0);
return(0);
} break;
default:break;
}
return (DefWindowProc(hwnd, msg, wparam, lparam));
}
首先看一下函数的参数,hwnd 是调用窗口的句柄,便于对窗口操作,msg有消息类型的信息,wparam,lparam包含具体消息的细节。
总之其实上面的都可以直接复制张贴,至于该怎么操作只需要改一下处理函数,还有在while循环里做些填充。
相关文章推荐
- Retain特质属性在MRC中的陷阱以及ARC中对其的规避
- Air中添加命令行参数的方法
- this class is not key value coding-compliant for the key pstype.'
- ibatis源码分析—配置文件解析(2)
- Redis学习笔记1-Redis安装
- java代码优化性能总结
- [LeetCode]Linked List Cycle II
- PAT 1067. Sort with Swap(0,*)
- [LeetCode]Linked List Cycle II
- JZ006: 捕获到 IO 例外:com.sybase.jdbc3.jdbc.SybConnectionDeadException: JZ0C
- android studio 快捷键
- LIKE,CHARINDEX,IN,EXISTS 效率分析汇总(补充中)
- VS2015中快捷注释代码块
- nopcommerce
- Android整理笔记
- noapic和acpi=off能帮我做到什么?
- 线上应用故障排查之二:高内存占用
- 访问CP15寄存器的指令
- OpenGL 坐标变换详解
- Hadoop和大数据:60款顶级开源工具