windows消息机制、消息格式和消息处理1
unicode支持,windows下用:
1、先在#include<windows.h>上面,定义 UNICODE
#define UNICODE
2、定义字符串
TCHAR * ptxt=TEXT("学习hello c++");
3、根据需要,打印不同格式字符串
#ifdef UNICODE
wprintf(L"%s\n",ptxt);
#else
printf("%s\n",ptxt);
#endif
打印UNICODE WriteConsole API函数:
HANDLE hstd=GetStdHandle(STD_OUTPUT_HANDLE);
wchar_t tc=300;
WriteConsole(hstd,&tc,1,NULL,NULL);
day66 am over
//winpro中,处理点击关闭时,返回0,退出消息循环(退出程序)
switch(msg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
}
//窗口类缓冲区大小,基于一个窗口类创建出来的所有窗口共享的缓冲区
wce.cbClsExtra=0;//数据是4的整数倍,一般200
//写入数据:
DWORD SetClassLong( HWND hWnd, // handle to window
int nIndex, // 字节索引
LONG dwNewLong // new value
);
//读取数据
DWORD GetClassLong( HWND hWnd, // handle to window
int nIndex // 字节索引
);
//窗口缓冲区大小,某一个窗口的数据缓冲区
wce.cbWndExtra=0;
//写入数据
LONG SetWindowLong( HWND hWnd, // handle to window
int nIndex, // 字节索引
LONG dwNewLong // new value
);
//获取数据
LONG GetWindowLong( HWND hWnd, // handle to window
int nIndex //字节索引
);
//系统消息格式
typedef struct tagMSG {
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
DWORD time;
POINT pt;
} MSG, *PMSG;
//在创建窗口之后还未显示的时候
case WM_CREATE:
OnCreate(hwnd,lparam);
void OnCreate(HWND hwnd,LPARAM lparam)
{
CREATESTRUCT *pcs=(CREATESTRUCT*)lparam;
//对应CreateWindowEx的12个参数
char * txt=(char *)pcs->lpCreateParams;//最后的附加参数
MessageBox(NULL,txt,"info",MB_OK);
}
day66 pm over
void OnSizeChange(HWND hwnd,LPARAM lparam)
{
int w=LOWORD(lparam);
int h=HIWORD(lparam);
HWND he=GetDlgItem(hwnd,1001);
MoveWindow(he,0,0,w,h);
}
//窗口大小变化时产生消息
case WM_SIZE:
OnSizeChange(hwnd,lparam)
break;
//windows发送消息
SendMessage//发送消息,等待消息返回
PostMessage//发送消息,不等待消息返回
PostMessage(hwnd,WM_QUIT,0,0);//发送退出消息
用户自定义消息定义(可用31743个),如下:
#define WM_MYMSG WM_USER+1
#define WM_MYMSG2 WM_USER+2
case WM_PAINT://窗口重新绘制
OnPaint(hwnd);
break;
case WM_LBUTTONDOWN://点击鼠标左键,
InvalidateRect(hwnd,NULL,NULL);//窗口重绘
break;
//窗口绘图
void OnPaint(HWND hwnd)
{
WriteConsole(g_houtput,"wm_paint\n",9,NULL,NULL);
PAINTSTRUCT ps={0};
HDC hdc=BeginPaint(hwnd,&ps);//必须在WM_PAINT消息处理函数中使用
TextOut(hdc,200,200,"hello",5);//绘制字符串到界面
EndPaint(hwnd,&ps);
}
键盘消息:
case WM_KEYDOWN://键盘按键消息
OnKeydown(hwnd,wparam);
break;
void OnKeydown(HWND hwnd,WPARAM wparam)
{
char txt[200]={0};
sprintf(txt,"wm_keydown:%08X,%d\n",wparam,wparam);//虚拟键码
WriteConsole(g_houtput,txt,strlen(txt),NULL,NULL);
switch(wparam)
{
case VK_UP:
g_ypos-=10;
if(g_ypos<0) g_ypos=0;
break;
case VK_DOWN:
g_ypos+=10;
break;
case VK_LEFT:
g_xpos-=10;
if(g_xpos<0) g_xpos=0;
break;
case VK_RIGHT:
g_xpos+=10;
break;
}
InvalidateRect(hwnd,NULL,TRUE);//重新绘制窗口
}
case WM_CHAR://translateMessage发送的,只有可见字符才能触发
on_char(hwnd,wparam,lparam);
void on_char(HWND hwnd,WPARAM wparam,LPARAM lparam)
{
char txt[200]={0};
sprintf(txt,"char code %08X,%d\n",wparam,wparam);//ascii码
WriteConsole(g_houtput,txt,strlen(txt),NULL,NULL);
}
鼠标消息:函数参数大致相同,查看MSDN Library就知道了。
case WM_LBUTTONDOWN://点击鼠标左键,
case WM_LBUTTONUP:
case WM_RBUTTONDOWN:
case WM_RBUTTONUP:
case WM_MOUSEMOVE:
case WM_LBUTTONDBLCLK://在注册窗口风格中要加 CS_DBLCLKS
case WM_RBUTTONDBLCLK:
case WM_MOUSEWHEEL:
case WM_MOUSELEAVE:
如:
case WM_LBUTTONUP://点击鼠标左键,
onLbuttondown(hwnd,wparam,lparam);
break;
void onLbuttondown(HWND hwnd,WPARAM wparam,LPARAM lparam)
{
char txt[200]={0};
if(wparam&MK_LBUTTON==MK_LBUTTON) wparam=wparam-MK_LBUTTON;//排除本身
if(wparam&MK_SHIFT==MK_SHIFT) {}//shift键按下
if(wparam&MK_RBUTTON==MK_RBUTTON) {}//右键按下
sprintf(txt,"其他键:%08X,x=%d,y=%d\n",wparam,LOWORD(lparam),HIWORD(lparam));//可见字符的ascii码
WriteConsole(g_houtput,txt,strlen(txt),NULL,NULL);
}
case WM_MOUSEMOVE://鼠标移动
OnMouseMove(hwnd,lparam);
break;
void OnMouseMove(HWND hwnd,LPARAM lparam)
{
char txt[200]={0};
sprintf(txt,"mouse move:x=%d,y=%d\n",LOWORD(lparam),HIWORD(lparam));//可见字符的ascii码
WriteConsole(g_houtput,txt,strlen(txt),NULL,NULL);
}
//鼠标双击的触发顺序:单击down,单击up,双击down,单击up
//在.h文件中加定义指定系统最低版本:
#define _WIN32_WINNT 0X400
case WM_MOUSEWHEEL://鼠标滚轮
OnMouseWheel(hwnd,wparam);
break;
void OnMouseWheel(HWND hwnd,WPARAM wparam){
short npy=HIWORD(wparam);//滚轮移动的偏移量
char txt[200]={0};
sprintf(txt,"OnMouseWheel:x=%d\n",npy);
WriteConsole(g_houtput,txt,strlen(txt),NULL,NULL);
}
定时器消息WM_TIMER://不太精确
UINT setTimer(HWND hwnd,UINT id)
{
SetTimer(hwnd,id,1000,timer1);//可以在这里直接指定处理函数
//SetTimer(hwnd,id,1000,NULL);//在WM_TIMER中捕捉再处理
return id;
}
//直接指定的处理函数
void CALLBACK timer1(HWND hwnd,UINT umsg,UINT uid,DWORD dwtime)
{
char txt[200]={0};
sprintf(txt,"timer1:id=%d\n",uid);
WriteConsole(g_houtput,txt,strlen(txt),NULL,NULL);
}
day68 pm 96
//在WM_TIMER中捕捉再处理
case WM_TIMER:
timer1Proc(hwnd,msg,wparam,lparam);
break;
LRESULT CALLBACK timer1Proc(
HWND hwnd, // handle to window
UINT uMsg, // WM_TIMER
WPARAM wParam, // timer identifier
LPARAM lParam // timer callback (TIMERPROC)
)
{
char txt[200]={0};
sprintf(txt,"timer1:id=%d\n",wParam);
WriteConsole(g_houtput,txt,strlen(txt),NULL,NULL);
return 0;
}
RECT rc={0};
GetClientRect(hwnd,&rc);//获取窗口边界
//画圆
RECT g_rc={0};
PAINTSTRUCT ps={0};
HDC hdc=BeginPaint(hwnd,&ps);//必须在WM_PAINT消息处理函数中使用
//TextOut(hdc,g_xpos,g_ypos,"hello",5);//绘制字符串到界面
Ellipse(hdc,g_rc.left,g_rc.top,g_rc.right,g_rc.bottom);
EndPaint(hwnd,&ps);
代码示例:
和day01一样,建立程序 ,
修改stdafx.h , 加一行: #define _WIN32_WINNT 0X400
修改主要cpp文件:
// win4.cpp : Defines the entry point for the application. // #include "stdafx.h" #include <stdio.h> HINSTANCE g_hinstance=0;//全局句柄 HANDLE g_houtput=0; HWND g_edit=0; int g_xpos=100; int g_ypos=100; #define WM_MYMSG WM_USER+1 UINT setTimer(HWND hwnd,UINT id) { SetTimer(hwnd,id,1000,NULL);//可以在这里指定处理函数,也可以在WM_TIMER中捕捉再处理 return id; } void SetExtra(HWND hwnd) { SetClassLong(hwnd,0,301); SetWindowLong(hwnd,0,401); } void GetExtra(HWND hwnd) { long nc= GetClassLong(hwnd,0); long nw=GetWindowLong(hwnd,0); char txt[200]={0}; sprintf(txt,"%d,%d",nc,nw); MessageBox(NULL,txt,"info",MB_OK); } void OnCreate(HWND hwnd,LPARAM lparam) { //g_edit=CreateWindowEx(0,"edit","hello",WS_CHILD|WS_VISIBLE|WS_BORDER,0,0, // 200,200,hwnd,NULL,g_hinstance,NULL); SendMessage(hwnd,WM_MYMSG,1,2); setTimer(hwnd,1023); //PostMessage(hwnd,WM_MYMSG,1,2); } void OnSizeChange(HWND hwnd,LPARAM lparam) { int width=LOWORD(lparam); int height=HIWORD(lparam); //改变窗口大小时,同时改编辑框大小 //MoveWindow(g_edit,0,0,width,height,TRUE); CHAR txt[40]={0}; sprintf(txt,"%d,%d\n",width,height); WriteConsole(g_houtput,txt,strlen(txt),NULL,NULL); } //窗口绘图 void OnPaint(HWND hwnd) { WriteConsole(g_houtput,"wm_paint\n",9,NULL,NULL); PAINTSTRUCT ps={0}; HDC hdc=BeginPaint(hwnd,&ps);//必须在WM_PAINT消息处理函数中使用 TextOut(hdc,g_xpos,g_ypos,"hello",5);//绘制字符串到界面 EndPaint(hwnd,&ps); } void OnKeydown(HWND hwnd,WPARAM wparam) { //WriteConsole(g_houtput,"wm_keydown\n",11,NULL,NULL); bool ischange=false; switch(wparam) { case VK_UP: g_ypos-=10; if(g_ypos<0) g_ypos=0; ischange=true; break; case VK_DOWN: g_ypos+=10; ischange=true; break; case VK_LEFT: g_xpos-=10; if(g_xpos<0) g_xpos=0; ischange=true; break; case VK_RIGHT: g_xpos+=10; ischange=true; break; } if(ischange) InvalidateRect(hwnd,NULL,TRUE); } void OnKeyup(HWND hwnd,WPARAM wparam) { char txt[200]={0}; sprintf(txt,"VIRTUAL KEY:%08X,%d\n",wparam,wparam);//虚拟键码 WriteConsole(g_houtput,txt,strlen(txt),NULL,NULL); } void on_char(HWND hwnd,WPARAM wparam,LPARAM lparam) { char txt[200]={0}; sprintf(txt,"char code %08X,%d\n",wparam,wparam);//可见字符的ascii码 WriteConsole(g_houtput,txt,strlen(txt),NULL,NULL); } void onLbuttondown(HWND hwnd,WPARAM wparam,LPARAM lparam) { char txt[200]={0}; if(wparam&MK_LBUTTON==MK_LBUTTON) wparam=wparam-MK_LBUTTON;//排除本身 if(wparam&MK_SHIFT==MK_SHIFT) {}//shift键按下 if(wparam&MK_RBUTTON==MK_RBUTTON) {}//右键按下 sprintf(txt,"onLbuttondown:其他键:%08X,x=%d,y=%d\n",wparam,LOWORD(lparam),HIWORD(lparam));//可见字符的ascii码 WriteConsole(g_houtput,txt,strlen(txt),NULL,NULL); } void OnMouseMove(HWND hwnd,LPARAM lparam) { char txt[200]={0}; g_xpos=LOWORD(lparam); g_ypos=HIWORD(lparam); sprintf(txt,"mouse move:x=%d,y=%d\n",g_xpos,g_ypos);//可见字符的ascii码 WriteConsole(g_houtput,txt,strlen(txt),NULL,NULL); InvalidateRect(hwnd,NULL,TRUE); } void OnLbuttonDBClk(HWND hwnd) { char txt[200]={0}; sprintf(txt,"OnLbuttonDBClk\n"); WriteConsole(g_houtput,txt,strlen(txt),NULL,NULL); } void OnMouseWheel(HWND hwnd,WPARAM wparam){ short npy=HIWORD(wparam);//滚轮移动的偏移量 char txt[200]={0}; sprintf(txt,"OnMouseWheel:x=%d\n",npy); WriteConsole(g_houtput,txt,strlen(txt),NULL,NULL); } void CALLBACK timer1(HWND hwnd,UINT umsg,UINT uid,DWORD dwtime) { char txt[200]={0}; sprintf(txt,"timer1:id=%d\n",uid); WriteConsole(g_houtput,txt,strlen(txt),NULL,NULL); } LRESULT CALLBACK timer1Proc( HWND hwnd, // handle to window UINT uMsg, // WM_TIMER WPARAM wParam, // timer identifier LPARAM lParam // timer callback (TIMERPROC) ) { char txt[200]={0}; sprintf(txt,"timer1:id=%d\n",wParam); WriteConsole(g_houtput,txt,strlen(txt),NULL,NULL); return 0; } //回调函数 LRESULT CALLBACK WinProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam) { switch(msg) { case WM_SYSCOMMAND: if(wparam==SC_CLOSE){ int ret=MessageBox(NULL,"是否退出","info",MB_YESNO); if(ret==IDYES){ //下面代码会自动关闭和销毁 //PostQuitMessage(0); } else return 0;//不执行下面代码 } break; //窗口大小变化时产生消息 case WM_SIZE: OnSizeChange(hwnd,lparam); break; case WM_CREATE: OnCreate(hwnd,lparam); break; case WM_DESTROY: //PostQuitMessage(0); PostMessage(hwnd,WM_QUIT,0,0); break; case WM_MYMSG://处理自定义消息 WriteConsole(g_houtput,"wm_mymsg\n",9,NULL,NULL); break; case WM_PAINT://窗口重新绘制 OnPaint(hwnd); break; case WM_LBUTTONDOWN://点击鼠标左键, onLbuttondown(hwnd,wparam,lparam); break; case WM_LBUTTONUP://点击鼠标左键, onLbuttondown(hwnd,wparam,lparam); break; case WM_RBUTTONDOWN: case WM_RBUTTONUP: break; case WM_MOUSEMOVE: //OnMouseMove(hwnd,lparam); break; case WM_MOUSEWHEEL://鼠标滚轮 OnMouseWheel(hwnd,wparam); break; case WM_LBUTTONDBLCLK://在注册窗口风格中要加 CS_DBLCLKS OnLbuttonDBClk(hwnd); break; case WM_RBUTTONDBLCLK: //InvalidateRect(hwnd,NULL,NULL);//窗口重绘 break; case WM_KEYDOWN://键盘按键消息 OnKeydown(hwnd,wparam); break; case WM_KEYUP://键盘按键消息 OnKeyup(hwnd,wparam); break; case WM_TIMER: timer1Proc(hwnd,msg,wparam,lparam); break; case WM_CHAR://translateMessage发送的,只有可见字符才能触发 //on_char(hwnd,wparam,lparam); break;; } return DefWindowProc(hwnd,msg,wparam,lparam); } //注册窗口类 BOOL Register(LPSTR 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|CS_DBLCLKS; ATOM atom= RegisterClassEx(&wce); if(atom==0){ MessageBox(NULL,"注册失败","info",MB_OK); return FALSE; } return TRUE; } //创建窗口 HWND CreateMain(LPSTR lpClassName,LPSTR lpWndName) { HWND hwnd=CreateWindowEx(0,lpClassName,lpWndName,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,g_hinstance,"hello create"); return hwnd; } //创建子窗口 HWND CreateChild(HWND phwnd,LPSTR lpClassName,LPSTR lpWndName) { if(Register(lpClassName,DefWindowProc)==0) { MessageBox(phwnd,"创建子窗口失败","info",MB_OK); return NULL; } //子窗口风格,都要 WS_CHILD|WS_VISIBLE HWND hwnd=CreateWindowEx(0,lpClassName,lpWndName,WS_CHILD|WS_VISIBLE|WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT, 200,200,phwnd,NULL,g_hinstance,NULL); return hwnd; } //显示窗口 void Display(HWND hwnd) { ShowWindow(hwnd,SW_SHOW); UpdateWindow(hwnd); } //处理消息 void MSGdeal() { MSG msg={0}; while(GetMessage(&msg,NULL,0,0)){ TranslateMessage(&msg);//翻译消息 DispatchMessage(&msg);//派发给 WinProc 处理消息 } // while(1) // { // if(PeekMessage(&msg,NULL,0,0,PM_NOREMOVE))//有消息 // { // if(!GetMessage(&msg,NULL,0,0)) return; // else // { // TranslateMessage(&msg);//翻译消息,只翻译可见字符 // DispatchMessage(&msg);//派发给 WinProc 处理消息 // } // } // else//无消息 // { // //WriteConsole(g_houtput,"nomsg\n",6,NULL,NULL); // //Sleep(1); // } // } } int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { AllocConsole();//调试程序方法 g_houtput=GetStdHandle(STD_OUTPUT_HANDLE); g_hinstance=hInstance; // TODO: Place code here. //SysReg(); //AppReg(); if(Register("main",WinProc)==0) { MessageBox(NULL,"注册失败","提示",MB_OK); return 0; } HWND hwnd= CreateMain("main","pro1"); Display(hwnd); // HWND hchild=CreateChild(hwnd,"child1","child1");//创建子窗口 // HWND hchild2=CreateChild(hwnd,"child2","child2"); // // MoveWindow(hchild,300,200,200,200,TRUE); // MoveWindow(hchild2,500,200,200,200,TRUE); // SetExtra(hchild); // GetExtra(hchild2); MSGdeal(); return 0; }