windows sdk绘图消息和键盘消息

 

绘图消息(WM_PAINT)

概念

  • 当产生无效区的时候,系统会发送VM_PAINT消息
  • 无效区:窗口需要重新绘制的部分
  • 设备上下文(hdc):可以理解为获取显示屏绘制属性的句柄

无效区产生时机

  1. 最小化恢复的时候
  2. 被覆盖的部分重新显示(win10 移除屏幕外)
  3. 窗口的尺寸被修改
  4. 还有一些API可以发送WM_PAINT消息(UpdateWindow)
  5. 拖动\鼠标移动\菜单,不会产生,因为系统做了优化

BeginPaint和GetDC的区别

  • BeginPaint会清除无效区,GetDC不会.
  • BeginPaint/EndPaint通常只在WM_PAINT消息中使用.
  • 两个API清理内存的函数不同

 

键盘消息

消息类型

  • 键盘按下(WM_KEYDOWN)
  • 键盘弹起(WM_KEYUP)

相关API

  • 将keydown消息转换为字符消息
  •  将keydown消息转换为字符消息 WM_CHAR  TranslateMessage(&msg)

  • 注意WM_CHAR  WM_KEYDOWN消息处理一个就可以了 不然会冲突默认进WM_KEYDOWN消息

  • 派发消息到对应的窗口过程函数    DispatchMessage(&msg)

  • WM_CHAR 对应的只是字符键而不是按键如esc键什么的。其中,字符是指的0-127内的ASCII码

// Win32Test.cpp : 定义应用程序的入口点。
//

#include "stdafx.h"
#include "Win32Test.h"

void ShowErrorMessage()
{
  LPVOID lpMsgBuf;

  //将错误码转化为错误信息,参数可以抄MSDN
  FormatMessage(
    FORMAT_MESSAGE_ALLOCATE_BUFFER |
    FORMAT_MESSAGE_FROM_SYSTEM |
    FORMAT_MESSAGE_IGNORE_INSERTS,
    NULL,
    GetLastError(),
    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
    (LPTSTR)&lpMsgBuf,
    0,
    NULL
    );
  // Process any inserts in lpMsgBuf.
  // ...
  // 弹出错误提示窗口.
  MessageBox(NULL, (LPCTSTR)lpMsgBuf, TEXT("Error"), MB_OK | MB_ICONINFORMATION);
  // Free the buffer.
  LocalFree(lpMsgBuf);
}


LRESULT CALLBACK MyWindowPro
(HWND hwnd,     // 窗口句柄
UINT uMsg,      // 消息标识
WPARAM wParam,  // 附加在消息上的参数
LPARAM lParam   // 附加在消息上的参数
)
{
  switch (uMsg)
  {
  //当产生无效区的时候,系统会发送VM_PAINT消息
  case WM_PAINT:
  {
                 /*使用beginPaint处理绘图消息*/
                 //BeginPaint会清除无效区,GetDC不会(不清除就会一直发送WM_PAINT消息).
                 //获取DC
                 PAINTSTRUCT ps;
                 HDC hDc = BeginPaint(hwnd, &ps);//此时会清除无效区

                 //绘制字符区域
                 RECT rc;
                 rc.left = 0;
                 rc.top = 0;

                 rc.right = 100;
                 rc.bottom = 100;

                 //绘制字符串
                 DrawText(hDc, TEXT("hello world"), 11, &rc, DT_CENTER);
                 //MessageBox(NULL, NULL, NULL, MB_OK);
                 EndPaint(hwnd, &ps);//用于释放内存
                 

                 ///*使用GetDC处理绘图消息*/
                 //GetDC不会清除无效区(不清除就会一直发送WM_PAINT消息)
                 //HDC hDc = GetDC(hwnd);

                 绘制字符区域
                 //RECT rc;
                 //rc.left = 100;
                 //rc.top = 100;

                 //rc.right = 1000;
                 //rc.bottom = 1000;

                 绘制字符串
                 //DrawText(hDc, TEXT("hello world"), 11, &rc, DT_CENTER);
                 //MessageBox(NULL, NULL, NULL, MB_OK);

                 //ReleaseDC(hwnd, hDc);//用于释放内存
                 break;
  }
  case WM_CHAR:
  {
                TCHAR sZ[0X255] = { 0 };
                wsprintf(sZ, TEXT("%c"), wParam);   //windows 当中的输入功能

                MessageBox(hwnd, sZ, TEXT("输入内容"), MB_OKCANCEL);
                break;
  }
  //case WM_KEYDOWN:
  //{
  //                   //判断0x14(capslk)键是否按下
  //                 if (GetKeyState(0x14) < 0)//如果是 < 0 那证明按键被按下了   
  //                 {
  //                   MessageBox(hwnd, TEXT("你按下了大写按键"), TEXT("消息!"), MB_OK);
  //                   return 0;
  //                 }

  //                 TCHAR sZ[0X255] = { 0 };
  //                 wsprintf(sZ, TEXT("%c"), wParam);   //windows 当中的输入功能

  //                 MessageBox(hwnd, sZ, TEXT("输入内容"), MB_OKCANCEL);
  //                 break;
  //}
 
    
    
  //点击关闭窗口会发送WM_CLOSE消息
  case WM_CLOSE:
  {
                 int nRet = MessageBox(hwnd, TEXT("是否退出"), TEXT("询问"), MB_OKCANCEL);
                 if (nRet == IDCANCEL)//取消关闭
                 {
                   return 0;
                 }
                 else
                 {
                   //摧毁窗口发送WM_DESTROY消息
                   DestroyWindow(hwnd);
                 }

                 break;
  }
    // 鼠标消息,左键按下
  case WM_LBUTTONDOWN:
  {
                       int xPos = LOWORD(lParam);
                       int yPos = HIWORD(lParam);
                       //产生无效区
                       InvalidateRect(hwnd, NULL, TRUE);
                       UpdateWindow(hwnd);
                       break;
  }
  case WM_DESTROY:
  {
                   //向消息队列投递WM_QUIT消息 WM_QUIT使消息循环退出,程序退出。
                   PostQuitMessage(0);
                   break;
  }
  default:
    break;
  }
  //系统默认处理消息窗口函数
  return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

ATOM MyRegisterClass(HINSTANCE hInstance)
{
  WNDCLASS wc;
  wc.style = CS_HREDRAW | CS_VREDRAW; //默认风格,窗口尺寸被修改后重画窗口
  wc.lpfnWndProc = MyWindowPro; //窗口回调,处理消息的(Windows消息处理用的是回调函数处理消息的,因为windows知道消息什么时候来并不知道怎么处理,所以通过回调去处理)
  wc.cbClsExtra = 0; //窗口类的额外空间 
  wc.cbWndExtra = 0; //窗口实例的额外空间
  wc.hInstance = hInstance;
  wc.hIcon = NULL; //图标
  wc.hCursor = NULL; //光标
  wc.hbrBackground = NULL;//背景
  wc.lpszMenuName = NULL;//菜单
  wc.lpszClassName = TEXT("MyWindow");

  ATOM nRet = RegisterClass(&wc);

  return nRet;
}

HWND MyCreatWindow(HINSTANCE hInstance)
{
  //创建窗口实例
  HWND hWnd = CreateWindow(
    TEXT("MyWindow"), //窗口类名
    TEXT("Hello World"), //窗口标题
    WS_OVERLAPPEDWINDOW, //重叠窗口
    CW_USEDEFAULT, CW_USEDEFAULT, //默认坐标
    CW_USEDEFAULT, CW_USEDEFAULT,//默认长和宽
    NULL, //没有父窗口
    NULL, //没有菜单
    hInstance,//main函数的实例句柄
    NULL//暂时不用,(LPVOID)0x87654093,可用来做参数标记
    );

  //显示窗口
  ShowWindow(hWnd, SW_SHOW);

  //更新窗口
  UpdateWindow(hWnd);

  return hWnd;
}

//句柄可以理解为标识ID,如窗口句柄就表示这个标识这个窗口的唯一ID
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,//应用程序当前实例的句柄
                     _In_opt_ HINSTANCE hPrevInstance,//应用程序的先前实例的句柄
                     _In_ LPTSTR    lpCmdLine,//指向应用程序命令行的字符串的指针
                     _In_ int       nCmdShow)//指明窗口如何显示,查msdn帮助文档,有各种宏
{

  ATOM nRet = MyRegisterClass(hInstance);
  if (nRet == 0)
  {
    ShowErrorMessage();
  }
  HWND hWnd = MyCreatWindow(hInstance);
  if (hWnd == NULL)
  {
    ShowErrorMessage();
  }


  MSG msg;
  //获取消息
  while (GetMessage(&msg, NULL, 0, 0) != 0)
  {
    //keydow消息和char消息不需要都实现,不然只会进入keydown消息
    //将keydown消息转换为字符消息
    TranslateMessage(&msg);

    //派发消息到对应的窗口过程函数
    DispatchMessage(&msg);
  }
  return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值