|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
这两天出去浪了 ,就没更新,本来想了半天开头怎么写,算了,直接进入正题吧
窗口程序的创建步骤:
1 定义WinMain入口函数
2 定义并赋值窗口类的数据
3 注册窗口类 RegisterClass
4 创建窗口 CreateWindow
5 显示窗口
ShowWindow/UpdateWindow
6 消息循环
GetMessage
TranslateMessage
DisptachMessage
7 定义窗口处理函数 WindowProc
创建窗口的基本步骤就是上面7条,这七条基本要讲好几期,下面我会先发一个窗口创建的完整源代码,并附上相关注释,之后再一条条详细解释
- #include "stdafx.h"
- //自定义(窗口处理函数)处理消息
- LRESULT CALLBACK WndProc(HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam)
- {
- switch (msgID)
- {
- case WM_DESTROY:
- PostQuitMessage(0);
- break;
- default:
- return DefWindowProc(hWnd, msgID, wParam, lParam);
- }
- return 0;
- }
- //WinMain入口函数
- int WINAPI WinMain(HINSTANCE hInstance, //当前程序实例句柄
- HINSTANCE hPrevInstance, //当前程序前一个实例句柄
- PSTR szCmdLince, ,//命令行参数字符串
- int iCmdShow)//窗口的显示方式
- {
- //注册窗口类
- WNDCLASS wc = { 0 };//定义并初始化窗口类的结构体数据
- wc.cbClsExtra = 0;//窗口类附加数据buff的大小
- wc.cbWndExtra = 0;//窗口附加数据buff的大小
- wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);//绘制窗口背景的画刷句柄
- wc.hCursor = NULL;//鼠标的句柄
- wc.hIcon = NULL;//窗口图标句柄
- wc.hInstance = hInstance;//当前模块的实例句柄
- wc.lpfnWndProc = WndProc;//窗口处理函数的名称
- wc.lpszClassName = _T("fishc");//窗口类的名称
- wc.lpszMenuName = NULL;//窗口菜单的资源ID字符串
- wc.style = CS_HREDRAW | CS_VREDRAW;//窗口类的风格
- RegisterClass(&wc);//将以上所有赋值全部写入操作系统
- HWND hWnd = CreateWindow(_T("fishc"), _T("fishc"),WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hInstance,NULL);
- //显示窗口
- ShowWindow(hWnd,SW_SHOW);
- UpdateWindow(hWnd);//刷新窗口
- //消息循环
- MSG nMsg= { 0 };
- while (GetMessage(&nMsg, NULL, 0, 0))
- {
- TranslateMessage(&nMsg);
- DispatchMessage(&nMsg);
- }
- return 0;
- }
复制代码
我们看到上面有很多我们不认识的英文,实际上都是给基本数据类型起的别名,下面附上常见的一些
- 大部分包含在basetsd.h,minwindef.h这两个头文件中
- typedef unsigned long ULONG;
- typedef unsigned short USHORT;
- typedef unsigned char UCHAR;
- #define CALLBACK __stdcall
- #define WINAPI __stdcall
- #define WINAPIV __cdecl
- #define APIENTRY WINAPI
- #define APIPRIVATE __stdcall
- #define PASCAL __stdcall
- typedef unsigned long DWORD;
- typedef int BOOL;
- typedef unsigned char BYTE;
- typedef unsigned short WORD;
- typedef float FLOAT;
- typedef int INT;
- typedef unsigned int UINT;
- typedef UINT_PTR WPARAM;
- typedef LONG_PTR LPARAM;
- typedef LONG_PTR LRESULT;
复制代码
1.窗口的注册
1.1窗口类
窗口类包含了窗口的各种参数信息的数据结构。每个窗口都具有窗口类,基于窗口类创建窗口。每个窗口类都具有一个名称,使用前必须注册到系统。
1.2窗口类的分类
1.2.1-系统窗口类
系统已经定义好的窗口类,不需要注册,直接使用窗口类即可,所有应用程序都可以直接使用。
例如按钮 - BUTTON窗口和编辑框 - EDIT窗口
- #include "stdafx.h"
- int APIENTRY WinMain(HINSTANCE hInstance,
- HINSTANCE hPrevInstance,
- LPSTR lpCmdLine,
- int nCmdShow)
- {
- //不需要注册类
- HWND hButton = CreateWindow( "EDIT", "OK",
- WS_OVERLAPPEDWINDOW,
- 100, 100, 500, 500, NULL, NULL,
- hInstance, NULL );
- ShowWindow( hButton, SW_SHOW );
- UpdateWindow( hButton );
- MSG nMsg = { 0 };
- while( GetMessage( &nMsg, NULL, 0, 0 ) )
- {
- TranslateMessage( &nMsg );
- DispatchMessage( &nMsg );//将消息交给窗口处理函数
- }
- return 0;
- }
复制代码
没有消息处理函数的窗口关闭后,进程并不会结束,需要自行到任务管理器中结束
1.2.2-应用程序全局窗口类
由用户自己定义,当前应用程序所有模块都可以使用。
1.2.3-应用程序局部窗口类
由用户自己定义,当前应用程序中本模块可以使用
既然说到了win32,还有以后可能会说的mfc,就不能不提最好的老师,msdn帮助手册,关于msdn手册哪里找,怎么下,我就不在赘述,但是我会提供官方的在线版,具体msdn有什么用,就先从一个实例讲起
- #include<windows.h>
- int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLince, int iCmdShow)
- {
- MessageBox(NULL,TEXT("这是我在鱼C学习的第一个程序"),TEXT("打招呼"),MB_OK);
- return 0;
- }
复制代码
这是小甲鱼课程中的代码,其中最关键的就是messagebox函数,这个函数有几个参数,参数具体是什么,有什么返回值,msdn中说的是非常详细了,在线地址
介绍完msdn,那么继续说窗口创建
一般应用程序窗口类的注册,常用函数是RegisterClass/RegisterClassEx,分别对应WNDCLASS/WNDCLASSEX两种结构体,EX只比普通多了两个参数,其他参数相同,所以以EX介绍为主RegisterClassEx函数
- ATOM WINAPI RegisterClassEx(
- _In_ const WNDCLASSEX *lpwcx//窗口类的数据
- );注册成功后,返回一个数字标识typedef WORD ATOM
复制代码
WNDCLASSEX函数
- typedef struct _WNDCLASSEX {
- UINT cbSize; //结构体的大小
- UINT style; //窗口类的风格
- WNDPROC lpfnWndProc; //窗口处理函数
- int cbClsExtra; //窗口类附加数据buff的大小
- int cbWndExtra; //窗口附加数据buff的大小
- HINSTANCE hInstance; //当前模块的实例句柄
- HICON hIcon; //窗口图标句柄
- HCURSOR hCursor; //鼠标的句柄
- HBRUSH hbrBackground; //绘制窗口背景的画刷句柄
- LPCTSTR lpszMenuName; //窗口菜单的资源ID字符串
- LPCTSTR lpszClassName; //窗口类的名称
- HICON hIconSm; //窗口的小图标句柄
- } WNDCLASSEX, *PWNDCLASSEX;
复制代码
应用程序全局窗口类的注册,需要在窗口类的风格中增加 CS_GLOBALCLASS,例如:
- WNDCLASSEX wce = {0};
- wce.style = CS_GLOBALCLASS;
复制代码
应用程序局部窗口类
在注册窗口类时,不添加CS_GLOBALCLASS风格创建,创建的就是局部窗口类。
1.3窗口类的风格
- CS_GLOBALCLASS - 应用程序全局窗口类
- CS_BYTEALIGNCLIENT - 窗口客户区的水平位置8倍数对齐
- CS_BYTEALIGNWINDOW - 窗口的水平位置8倍数对齐
- CS_HREDRAW - 当窗口水平变化时,窗口重新绘制
- CS_VREDRAW - 当窗口垂直变化时,窗口重新绘制
- CS_DBLCLKS - 允许窗口接收鼠标左键双击
- CS_NOCLOSE - 窗口没有关闭按钮
复制代码
- #include "stdafx.h"
- HINSTANCE g_hInstance = 0;//全局句柄接收当前程序实例句柄
- void AppReg( )
- {
- WNDCLASSEX wce = { 0 };
- wce.cbSize = sizeof(wce);
- wce.cbClsExtra = 0;
- wce.cbWndExtra = 0;
- wce.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
- wce.hCursor = NULL;
- wce.hIcon = NULL;
- wce.hIconSm = NULL;
- wce.hInstance = g_hInstance;
- wce.lpfnWndProc = DefWindowProc;
- wce.lpszClassName = "Main";
- wce.lpszMenuName = NULL;
- wce.style = CS_HREDRAW | CS_VREDRAW;
- RegisterClassEx( &wce );//将以上所有赋值全部写入操作系统
- HWND hWnd = CreateWindow( "Main", "window",
- WS_OVERLAPPEDWINDOW,
- 100, 100, 500, 500, NULL, NULL, g_hInstance,
- NULL );
- ShowWindow( hWnd, SW_SHOW );
- UpdateWindow( hWnd );
- MSG nMsg = { 0 };
- while( GetMessage( &nMsg, NULL, 0, 0 ) )
- {
- TranslateMessage( &nMsg );
- DispatchMessage( &nMsg );
- }
- }
- int APIENTRY WinMain(HINSTANCE hInstance,
- HINSTANCE hPrevInstance,
- LPSTR lpCmdLine,
- int nCmdShow)
- {
- g_hInstance = hInstance;//接收当前程序实例句柄
- AppReg( );
- return 0;
- }
复制代码
2.窗口的创建
2.1窗口类的查找过程
2.1.1系统根据传入的窗口类名称,在应用程序局部窗口类中查找,如果找到执行2,如果未找到执行3。
2.1.2比较局部窗口类与创建窗口时传入的HINSTANCE变量。如果发现相等,创建和注册的窗口类在同一模块,创建窗口返回。如果不相等,继续执行3。
2.1.3在应用程序全局窗口类,如果找到,执行4,如果未找到执行5。
2.1.4使用找到的窗口类的信息,创建窗口返回。
2.1.5在系统窗口类中查找,如果找到创建窗口返回,否则创建窗口失败。
当窗口注册完毕并将数据写入系统后,就可以开始窗口的创建了,窗口注册函数CreateWindow/CreateWindowEx
CreateWindowEx函数
- HWND CreateWindowEx(
- DWORD dwExStyle, //窗口的扩展风格
- LPCTSTR lpClassName, //已经注册的窗口类名称
- LPCTSTR lpWindowName, //窗口标题栏的名字
- DWORD dwStyle, //窗口的基本风格,[url=https://msdn.microsoft.com/en-us/library/windows/desktop/ms632600(v=vs.85).aspx]Window Styles[/url]
- int x, //窗口左上角水平坐标位置
- int y, //窗口左上角垂直坐标位置
- int nWidth, //窗口的宽度
- int nHeight,//窗口的高度
- HWND hWndParent,//窗口的父窗口句柄
- HMENU hMenu,//窗口菜单句柄
- HINSTANCE hInstance, //应用程序实例句柄
- LPVOID lpParam //窗口创建时附加参数
- ); 创建成功返回窗口句柄
复制代码
2.2创建子窗口
如果你上面每句话都细心琢磨的话,会发现好多参数都有前或者父这种说法,所以在一个窗口下还能创建一个子窗口,要点主要有两个
2.2.1创建时要设置父窗口句柄
2.2.2创建风格要增加 WS_CHILD|WS_VISIBLE
- #include "stdafx.h"
- #include "stdio.h"
- HINSTANCE g_hInstance = 0;//接收当前程序实例句柄
- //自定义(窗口处理函数) 处理消息
- LRESULT CALLBACK WndProc( HWND hWnd, UINT msgID,
- WPARAM wParam, LPARAM lParam )
- {
- switch( msgID )
- {
- case WM_DESTROY:
- PostQuitMessage( 0 );//使GetMessage函数返回0???
- break;
- }
- return DefWindowProc( hWnd, msgID, wParam, lParam );
- }
- //注册窗口类
- void Register( LPCTSTR lpClassName, WNDPROC wndproc )
- {
- WNDCLASSEX wce = { 0 };
- wce.cbSize = sizeof( wce );
- wce.cbClsExtra = 0;
- wce.cbWndExtra = 0;
- wce.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
- wce.hCursor = NULL;
- wce.hIcon = NULL;
- wce.hIconSm = NULL;
- wce.hInstance = g_hInstance;
- wce.lpfnWndProc = wndproc;/***************/
- wce.lpszClassName = lpClassName;
- wce.lpszMenuName = NULL;
- wce.style = CS_HREDRAW | CS_VREDRAW;
- RegisterClassEx( &wce );
- }
- //创建主窗口
- HWND CreateMain( LPCTSTR lpClassName, LPCTSTR lpWndName )
- {
- HWND hWnd = CreateWindowEx( 0, lpClassName, lpWndName,
- WS_OVERLAPPEDWINDOW, 100, 100, 700, 500,
- NULL, NULL, g_hInstance, NULL );
- return hWnd;
- }
- //创建子窗口
- HWND CreateChild( LPCTSTR lpClassName, LPCTSTR lpWndName,
- HWND hParent )
- {
- HWND hChild = CreateWindowEx( 0, lpClassName, lpWndName,
- WS_CHILD|WS_VISIBLE|WS_OVERLAPPEDWINDOW,
- 100, 100, 200, 200, hParent, NULL,
- g_hInstance, NULL );
- return hChild;
- }
- //显示窗口
- void Display( HWND hWnd )
- {
- ShowWindow( hWnd, SW_SHOW );
- UpdateWindow( hWnd );
- }
- //消息循环
- void Message( )
- {
- MSG nMsg = { 0 };
- while( GetMessage(&nMsg, NULL, 0, 0) )
- {
- TranslateMessage( &nMsg );
- DispatchMessage( &nMsg );//将消息交给窗口处理函数。
- }
- }
- int APIENTRY WinMain(HINSTANCE hInstance,
- HINSTANCE hPrevInstance,
- LPSTR lpCmdLine,
- int nCmdShow)
- {
- g_hInstance = hInstance;
- Register( "Main", WndProc );
- HWND hWnd = CreateMain( "Main", "window" );
- Register( "Child", DefWindowProc );
- HWND hChild1 = CreateChild( "Child", "c1", hWnd );
- HWND hChild2 = CreateChild( "Child", "c2", hWnd );
- Display( hWnd );
- MoveWindow( hChild1, 100, 100, 200, 200, TRUE );//移动窗口位置和大小,(窗口句柄,水平坐标,垂直坐标,宽度,高度,是否擦除原来位置上的窗口图像)
- MoveWindow( hChild2, 400, 100, 200, 200, TRUE );//[url=https://msdn.microsoft.com/EN-US/library/windows/desktop/ms633534(v=vs.85).aspx]MoveWindow函数[/url]
- Message( );
- return 0;
- }
复制代码
2.3窗口类和窗口的附加数据
注册窗口时,可以设置这两个数据内存空间的大小。
- int cbClsExtra; //窗口类附加数据buff的大小
- int cbWndExtra; //窗口附加数据buff的大小
复制代码
可以提供窗口类和窗口存放自己的数据的空间。
2.3.1窗口类附加数据的使用
2.3.1.1定义数据空间的大小
- int cbClsExtra - 一般定义为4字节倍数
复制代码
2.3.1.2存入数据(SetClassLong)
- DWORD SetClassLong(
- HWND hWnd,//窗口句柄
- int nIndex,//字节索引号(从哪个字节开始存)
- LONG dwNewLong //存入的数据
- );返回旧数据
复制代码
2.3.1.3读取数据(GetClassLong)
- DWORD GetClassLong(
- HWND hWnd, //窗口句柄
- nt nIndex //字节索引号(从哪个字节开始读)
- ); 返回获取值
复制代码
2.3.2窗口附加数据的使用
2.3.2.1定义数据空间的大小
2.3.2.2存入数据(SetWindowLong)
- LONG SetWindowLong(
- HWND hWnd, // 窗口句柄
- int nIndex, // 字节索引号(从哪个字节开始存)
- LONG dwNewLong // 存入的数据
- );
复制代码
2.3.2.3读取数据(GetWindowLong)
- LONG GetWindowLong(
- HWND hWnd, // 窗口句柄
- int nIndex // 字节索引号(从哪个开始读)
- );//返回值获取读到的数据
复制代码
- #include "stdafx.h"
- #include "stdio.h"
- HINSTANCE g_hInstance = 0;//接收当前程序实例句柄
- //自定义(窗口处理函数) 处理消息
- LRESULT CALLBACK WndProc( HWND hWnd, UINT msgID,
- WPARAM wParam, LPARAM lParam )
- {
- switch( msgID )
- {
- case WM_DESTROY:
- PostQuitMessage( 0 );//使GetMessage函数返回0???
- break;
- }
- return DefWindowProc( hWnd, msgID, wParam, lParam );
- }
- //注册窗口类
- void Register( LPCTSTR lpClassName, WNDPROC wndproc )
- {
- WNDCLASSEX wce = { 0 };
- wce.cbSize = sizeof( wce );
- wce.cbClsExtra = 200;
- wce.cbWndExtra = 200;
- wce.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
- wce.hCursor = NULL;
- wce.hIcon = NULL;
- wce.hIconSm = NULL;
- wce.hInstance = g_hInstance;
- wce.lpfnWndProc = wndproc;/***************/
- wce.lpszClassName = lpClassName;
- wce.lpszMenuName = NULL;
- wce.style = CS_HREDRAW | CS_VREDRAW;
- RegisterClassEx( &wce );
- }
- //创建主窗口
- HWND CreateMain( LPCTSTR lpClassName, LPCTSTR lpWndName )
- {
- HWND hWnd = CreateWindowEx( 0, lpClassName, lpWndName,
- WS_OVERLAPPEDWINDOW, 100, 100, 700, 500,
- NULL, NULL, g_hInstance, NULL );
- return hWnd;
- }
- //创建子窗口
- HWND CreateChild( LPCTSTR lpClassName, LPCTSTR lpWndName,
- HWND hParent )
- {
- HWND hChild = CreateWindowEx( 0, lpClassName, lpWndName,
- WS_CHILD|WS_VISIBLE|WS_OVERLAPPEDWINDOW,
- 100, 100, 200, 200, hParent, NULL,
- g_hInstance, NULL );
- return hChild;
- }
- //显示窗口
- void Display( HWND hWnd )
- {
- ShowWindow( hWnd, SW_SHOW );
- UpdateWindow( hWnd );
- }
- //消息循环
- void Message( )
- {
- MSG nMsg = { 0 };
- while( GetMessage(&nMsg, NULL, 0, 0) )
- {
- TranslateMessage( &nMsg );
- DispatchMessage( &nMsg );//将消息交给窗口处理函数。
- }
- }
- //存入数据
- void SetExtra( HWND hWnd )
- {
- SetClassLong( hWnd, 0, 100);
- SetWindowLong( hWnd, 0, 100 );
- }
- //读取数据
- void GetExtra( HWND hWnd )
- {
- DWORD nClass = GetClassLong( hWnd, 0 );
- DWORD nWnd = GetWindowLong( hWnd, 0 );
- char szText[256] = { 0 };
- sprintf( szText, "窗口类附加数据缓冲区:%d,窗口附加数据缓冲区:%d", nClass, nWnd );
- MessageBox( hWnd, szText, "Infor", MB_OK );
- }
- int APIENTRY WinMain(HINSTANCE hInstance,
- HINSTANCE hPrevInstance,
- LPSTR lpCmdLine,
- int nCmdShow)
- {
- g_hInstance = hInstance;
- Register( "Main", WndProc );
- HWND hWnd = CreateMain( "Main", "window" );
- Register( "Child", DefWindowProc );
- HWND hChild1 = CreateChild( "Child", "c1", hWnd );
- HWND hChild2 = CreateChild( "Child", "c2", hWnd );
- Display( hWnd );
- MoveWindow( hChild1, 100, 100, 200, 200, TRUE );
- MoveWindow( hChild2, 400, 100, 200, 200, TRUE );
- SetExtra( hChild1 );
- GetExtra( hChild2 );
- Message( );
- return 0;
- }
复制代码
2.4使用两种附加数据的不同
2.4.1窗口类附加数据缓冲区:是基于同一个窗口类创建出来的所有窗口共享的缓冲区。
2.4.2窗口附加数据缓冲区:是窗口自己私有的缓冲区,即便是基于同一个窗口类创建出来的窗口相互之间也不共享。
下期预告:windows消息机制 |
评分
-
查看全部评分
|