欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

孙鑫01

发布时间:2024/1/1 编程问答 50 豆豆
生活随笔 收集整理的这篇文章主要介绍了 孙鑫01 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

1.消息和事件

用户在操作系统中任何一个操作都是事件。比如鼠标单击了一个按钮就是一个鼠标事件。消息是操作系统将事件传递给用户程序的数据格式,是一种数据通讯协议。操作系统将每个事件都包装成一个称为消息的结构体MSG来传递给应用程序。
MSG结构定义如下:

typedef struct tagMSG {HWND hwnd; //窗口句柄UINT message;//消息WPARAM wParam;LPARAM lParam;DWORD time;POINT pt; } MSG;
  • 句柄,资源的标识,操作系统要管理和操作这些资源,都是通过句柄来找到对应的资源。句柄又可以分为图标句柄(HICON),光标句柄(HCURSOR),窗口句柄(HWND),应用程序实例句柄(HINSTANCE)。操作系统给每一个窗口指定一个唯一的标识号即窗口句柄。
  • 消息,实质是整数,为了便于记忆采用了宏的形式,比如用WM_开头的各种窗口消息。
  • WParam LParam都是整型,表示消息的附加信息。比如WM_CHAR消息,WParam用来存放按键的ASCII码,LParam比较复杂,MSDN说明如下:
    The repeat count, scan code, extended-key flag, context code, previous key-state flag, and transition-state flag, as shown in the following table.
    Bits Meaning
    0-15 The repeat count for the current message. The value is the number of times the keystroke is autorepeated as a result of the user holding down the key. If the keystroke is held long enough, multiple messages are sent. However, the repeat count is not cumulative.
    16-23 The scan code. The value depends on the OEM.
    24 Indicates whether the key is an extended key, such as the right-hand ALT and CTRL keys that appear on an enhanced 101- or 102-key keyboard. The value is 1 if it is an extended key; otherwise, it is 0.
    25-28 Reserved; do not use.
    29 The context code. The value is 1 if the ALT key is held down while the key is pressed; otherwise, the value is 0.
    30 The previous key state. The value is 1 if the key is down before the message is sent, or it is 0 if the key is up.
    31 The transition state. The value is 1 if the key is being released, or it is 0 if the key is being pressed.
  • DWORD 记录消息发送的时间
  • POINT 记录光标的位置

2.windows的入口函数

int WINAPI WinMain {HINSTANCE hInstance, //handle to current instanceHINSTANCE hPreInstance, //handle to previous instanceLPSTR lpCmdLine, //command lineint nCmdShow //show state
  • hPreInstance 比如有两个一样的程序,就有当前和先前之分了。如果只有一个程序,那么hPreInstance应该为空
  • LPSTR 长指针,类似于char*。命令行参数 比如在windows运行栏中输入 notepad 1.txt 就能启动1.txt
    这就是命令行参数。下图是如何设定一个命令行参数。
  • nCmdShow 显示状态,比如窗口的最大化 最小化 隐藏显示等
    注意WinMain函数是由操作系统调用的。

2.创建一个完整窗口的步骤

  • 设计一个窗口
  • 注册一个窗口
  • 创建一个窗口
  • 显示及更新一个窗口
    在我们的程序中,经常要用到一类变量,这个变量的每一位,都对应一种特性,当该变量的某位为1时,表示有该位对应的那种特性,当该位为0时,即没有该位所对应的那种特性。当变量中的某几位同时为1时,就表示同时具有几种特性的组合。一个变量中的哪一位代表哪种意义不容易记忆,所以我们根据特征的英文拼写的大写去定义一些宏,我们可以用二进制or|操作符将他们进行或运算相组合。如果要去掉某个特征,去反~之后再进行&运算就可以实现。例如style &~CS_NOCLOSE
    窗口类
typedef struct tagWNDCLASSEXW {UINT cbSize; /* Win 3.x */UINT style; //窗口拉伸时是否重绘WNDPROC lpfnWndProc;//回调函数指针int cbClsExtra; // 窗口类的附加内存,通常为0int cbWndExtra; //窗口附加内存,通常为0HINSTANCE hInstance; //当前应用程序实例号HICON hIcon; //图表句柄HCURSOR hCursor; // HBRUSH hbrBackground;LPCWSTR lpszMenuName;LPCWSTR lpszClassName;/* Win 4.0 */HICON hIconSm; } WNDCLASSEXW,
  • WNDPROC lpfnWndProc回调函数指针。回调函数的原理是这样的,当应用程序收到给某一个窗口的消息时,就应该调用某一函数来处理这条消息。这一调用过程不用应用程序自己来实施,而由操作系统来完成,但是回调函数本身的代码必须由应用程序自己来完成。对于一条消息,操作系统到底调用应用程序中的那个函数来处理呢,操作系统就调用接受消息的窗口所属类型中的lpfnWndProc成员指定的函数,每一种不同类型的窗口都有自己专用回调函数,该函数就是通过lpfnWndProc成员指定
    WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);wcex.style = CS_HREDRAW | CS_VREDRAW; //竖向拉伸 水平拉伸是否要重绘wcex.lpfnWndProc = WndProc; //回调函数指针wcex.cbClsExtra = 0; //窗口类是否要额外字节wcex.cbWndExtra = 0; //窗口是否要额外字节wcex.hInstance = hInstance; //窗口句柄wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MY));//指定图表wcex.hCursor = LoadCursor(NULL, IDC_ARROW);//指定光标wcex.hbrBackground = (HBRUSH)(DKGRAY_BRUSH);//指定窗口背景wcex.lpszMenuName = MAKEINTRESOURCE(IDC_MY); //菜单的名字wcex.lpszClassName = szWindowClass; //类的名字wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

3.HWND和HINSTANCE的区别

hWnd,是指窗口句柄,通过该句柄可以操作窗口资源;hInstance是应用程序句柄,是操作系统分配给实例的指针. 程序根据hInstance访问其相应的内存空间。
应用程序一定有hInstance,但不一定有hWnd.

4.注册窗口

在用WNDCLASS设定好窗口的相关参数后,调用RegisterClass(&wndclass)就可以实现窗口类的注册

5.创建窗口

先定义一个句柄

HWND hwnd; CreatWindow(LPCTSTR lpClassName //register calss name 即在wndclass注册的类名,否则启动不了窗口LPCTSTR lpWindowName//window nameDWORD dwStyle //window styleint x //horizental position of windowint y //vertical position of windowint nWidth //window widthint nHeight //window heightHWND hWndParent //handle to parent or owner windowHINSTANCE hInstance //handle to application instanceLPVOID lpParam //window creation data);

6.显示窗口

ShowWindow(HWnd,int nCmdShow)

7.更新窗口

UpDateWindow(hwnd)

8.消息循环

MSG msg;
while(GetMessage(&MSG,NULL,0,0))

TranslateMessage(&MSG);
DispatchMessage(&MSG);


GetMessage是从消息队列中获取消息,
GetMessage{
LPMSG lpMsg //message information
HWND hwnd //handle to window
UINT wMsgFilterMin,//first message
UINT wMsgFilterMax //last message

HWND hwnd=NULL时表示调用线程的任何窗口的消息,也就是获取所有的消息
wMsgFilterMin,wMsgFilterMax为NULL时表示接受所有的消息
返回值为bool,有返回值时即为真

  • TranslateMessage(&MSG)
    消息转化,对取到的消息对转化。比如keydown和keyup消息时,能转化到WM_char消息,并将转换后的消息投放到消息队列中,只会产生新消息,不会影响原来的消息
  • DispatchMessage(&MSG)
    将搜到的消息传到窗口回调函数中处理。将消息路由到操作系统,然后操作系统调用窗口的回调函数。

9.窗口过程的回调函数

LRESULT CALLBACK WindowProc

HWND hwnd,
MSG msg,
WParam wParam,
LParam lParam,

10.BeginPaint 和EndPaint

PAINTSTRUCT ps;
HDC hdc;
switch(umsg)

case WM_PAINT:
{
hdc=BeginPaint (hwnd,&ps);
EndPaint(hwnd,&ps);
break;
}

注意WM_PAINT中只能使用BeginPaint 和EndPaint,
GetDC和RRelaeaseDC不能再这里使用

11.关闭窗口消息WM_Close

case WM_Close:
if(IDYES==MessageBox(hend,“你是否要退出程序”,“维新”,MB_YESNO))
{
DestroyWindow(hwnd); //销毁窗口,并发送WM_DESTROY消息,但不销毁程序
}
break;

12.WM_DESTROY

case WM_DESTROY:
PostQuitMessage(0);
break;
通知系统线程请求终止,其形参是给出应用程序退出的代码,其值作为WM_QUIT消息的附加参数,放到WParam中。发出的WM_QUIT消息发送到线程消息队列中。PostQuitMessage()返回值为0,使GetMessage得到0值,退出程序。

13.缺省消息处理

default :
return DefWindowProc(hwnd,uMSG,WParam,LParam);
让系统处理我们没有定义的消息,注意此处不能缺省,不然无法正常启动程序

总结

以上是生活随笔为你收集整理的孙鑫01的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。