win32Day03重要消息

目录

0x00重要消息:

鼠标消息

键盘消息

系统消息:

定时器消息 WM_TIMER

WM_PAINT消息:

设备改变

自定义消息


 

 

0x00重要消息:

  1. 鼠标消息

    1. 鼠标消息分类
      1. 鼠标移动消息 WM_MOUSEMOVE
      2. 鼠标左键:
        1. 鼠标左键按下消息 WM_LBUTTONDOWN
        2. 鼠标左键弹起消息 WM_LBUTTONUP
        3. 鼠标左键双击消息 WM_LBUTTONDBLCLK
      3. 鼠标右键:
        1. 鼠标右键按下消息 WM_RBUTTONDOWN
        2. 鼠标右键弹起消息 WM_RBUTTONUP
        3. 鼠标右键双击消息 WM_RBUTTONDBLCLK
      4. 滚轮消息:WM_MOUSEWHELL
      5. 中键消息:
        1. WM_MBUTTONDOWN
        2. WM_MBUTTONUP
        3. WM_MBUTTONDBCLK
    2. (重点)鼠标消息的附加信息(两者都是DWORD类型的数据 4个字节,分为高16位和低16位)
      //套路
      POINT pos
      pos.y = HIWORD(lParam);
      pos.x = LOWORD(lParam);
      1. lParam 只是用来记录鼠标的客户区坐标,高16位为y坐标,低16位为x坐标
      2. wParam 用来存储鼠标消息的按键动作,鼠标消息中存储的按键信息不是虚拟键值,而是某个键的标记,以MK_开头
    3. 单击:在同一个点按下并且弹起叫做单击,在一个地方按下,在另一个地方弹起不叫单击
    4. 双击:在同一个地方快速单击两次
    5. 要产生鼠标双击消息需要在注册窗口的时候添加风格:CS_DBLCLKS 并且鼠标双击消息会覆盖掉第二次单击消息
    6. #include <windows.h>
      WNDCLASS wc;	
      wc.style = CS_DBLCLKS;

       

  2. 键盘消息

    1. WM_KEYUP
    2. WM_KEYDOWN
    3. WM_SYSKEYUP
    4. WM_SYSKEYDOWN
    5. 系统键:alt F10
    6. 其他键:除了 alt 和F10以外的其他键。
    7. 如何区分键盘上的按键?通过虚拟键值(就是一个整数,一个整数对应了一个按键,基本和ASCII码相同) 在winuser.h头文件中定义了很多个宏,是对应的虚拟键值。
    8. 键盘消息的附加信息,lParam没有用,wParam用来保存虚拟键值。
      1. 虽然按下除alt和F10以外的每个键都会产生WM_KEYUP消息,松开都会产生WM_KEYDOWN消息,但是,不同的键产生附加信息中保存的虚拟键值是不同的
      2. 准确的说是LOWORD(wParam)保存虚拟键值,HIWORD(wParam)没有用。所以LOWORD(wParam) 的值和wParam的值可以认为是一样的。
    9. 系统键盘消息:只有alt键和F10不会产生WM_KEYUP和WM_KEYDOWN消息,他们会产生WM_SYSKEYUP,WM_SYSKEYDOWN 消息
  3. 系统消息:

    1. WM_SIZE:
      1. 窗口大小发生变化时产生
      2. 非队列消息
      3. wParam没有用
      4. lParam用来保存创建窗口时的信息。
        1. 用CREATESTRUCT类型的结构来保存。
        2. HIWORD(lParam)用来描述窗口的高。
        3. LOWORD(lParam)用来保存窗口的宽。
        4. PrintHeightWidth():
          //输出当前窗口的宽和高
          void PrintHeightWidth(LPARAM lParam){
              MyPrintf(“Height:%d\n",HIWORD(lParam));
              MyPrintf("Width:%d\n",LOWORD(lParam));
          }

           

    2. WM_CREATE:
      1. 窗口创建后,显示前发送。
      2. 非队列消息,不进入消息队列,直接被发送给消息处理函数
      3. 一般用来做初始化操作。套路:将一系列初始化操作,例如申请控制台的使用权限呀什么的都封装在一个OnCreate函数中。
  4. 定时器消息 WM_TIMER

    1. 由操作系统内核发送
    2. 定时器可以设置多个
    3. 设置定时器:设置一个定时器,每隔多少时间就发送一次定时器消息,或者调用一次定时器处理函数
      //设置定时器
      UINT SetTimer(
              HWND hwnd,//窗口句柄
              UINT nIDEvent,//设置定时器的ID,程序员设置,如果为NULL,则编译器会自动设置
              UINT uElapse, //设置定时器的间隔时间
              TIMERPROC lpTimerFunc//设置定时器的处理函数 如果设置为NULL,就会触发定时器消息
      );
      /*
      定时器有两种响应方式,一种是定时器消息响应,一种是定时器处理函数响应。
      建议大家写定时器处理函数。
      因为如果有多个定时器,通过定时器消息来响应,需要在消息中区分不同定时器的ID,比较麻烦。
      不如一开始在SetTimer中就区分好。
      
      每个定时器一旦设置好
      就会每隔设置间隔的uElapse时间
      调用一次设置好的定时器处理函数lpTimerFunc。
      或者发送一次WM_TIMER消息
      */
      

       

    4. 定时器消息响应
      void OnCreate(HWND hwnd){
      	SetTimer(hwnd,007,500,NULL);//500ms = 0.5s
          SetTimer(hwnd,008,1000,NULL);
      }
      case WM_CREATE:
          OnCreate(hwnd);
          break;
      case WM_TIMER:
          switch(LOWORD(wParam)){
              case 7:
                  MessageBox(hwnd,"主人,该喝水啦!","喝水小助手",MB_OK);
                  break;
              case 8:
                  MessageBox(hwnd,"老大,该释放内存了!",“您的仆人”,MB_OK);
                  break;
          } 
          break;

      LOWORD(wParam) == 发送定时器消息的定时器的ID

    5. 定时器函数响应
    6. 补充:最小操作系统
      1. 晶振
      2. CPU:计算
      3. ram(内存)
      4. 总线:数据传输的通道
  5. WM_PAINT消息:

    1. 窗口需要重新绘制的时候发送此消息,窗口大小发生改变的时候都要重新绘制该窗口。
    2. 窗口的标题栏和菜单栏不是自己绘制出来的,是操作系统绘制出来的。只有除标题栏和菜单栏以外的部分是窗口自己绘制出来的。而WM_PAINT消息只在窗口自己重新绘制自己时,才会发生
    3. 绘图需要命令操作系统的绘图设备(即显卡)绘制图形,为此首先要得到绘图设备句柄 hDc,这样应用程序才能向显卡发指令。发送指令需要绘图设备框架,这个框架有两种写法。

      1. beginPaint:用来从操作系统那里拿到绘图句柄 。
      2. endPaint:用来在绘图句柄使用完之后,将绘图句柄还给操作系统。
      3. getDc:
      4. ReleaseDc:
    4. 如何绘图?使用绘图的函数
    5. 画任何图形都是画矩形,即一个虚线矩形框中可以包含任何图形,一个矩形就是两个点,左上角的点(left,top)和右下角的点(right,bottom)
  6. 设备改变消息WM_DEVICECHANGE:

    1. case WM_DEVICECHNAGE:
          MessageBox(NULL,"设备改变",NULL,NULL);
          break;
      
      

      通过该消息可以实现这样一个小程序:当别人插入u盘时,会触发WM_DEVICECHANGE消息。这时让程序在后台自动拷贝对方U盘上的所有内容。岂不美哉。

    2. 可以根据LOWORD(wParam)来判断不同的设备。

  7. 自定义消息

  8. // WindowsProject1.cpp : 定义应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include "WindowsProject1.h"
    #include <string.h>
    #include <stdio.h>
    
    #define MAX_LOADSTRING 100
    
    // 全局变量:
    HINSTANCE hInst;                                // 当前实例
    WCHAR szTitle[MAX_LOADSTRING];                  // 标题栏文本
    WCHAR szWindowClass[MAX_LOADSTRING];            // 主窗口类名
    HANDLE g_hConsole;
    
    // 此代码模块中包含的函数的前向声明:
    ATOM                MyRegisterClass(HINSTANCE hInstance);
    BOOL                InitInstance(HINSTANCE, int);
    LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
    INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);
    int count = 0;
    HWND g_hWnd;
    void timerProc() {
    	WriteConsole(g_hConsole, L"ci贼帅",wcslen(L"ci贼帅"),NULL, NULL);
    	if (count++ > 15)
    		KillTimer(g_hWnd, 6666);
    }
    void On_Create(HWND hWnd,WPARAM wParam,LPARAM lParam) {
    	AllocConsole();//获取控制台应用程序的权限
    	g_hConsole=GetStdHandle(STD_OUTPUT_HANDLE);//获取控制台应用程序的标准输出句柄,赋值给全局变量g_hConsole
    	//设置一个定时器
    	SetTimer(hWnd,666,1000, NULL);//窗口应用程序句柄,定时器id,间隔时间,定时器的处理函数(设置为空,将会发送定时器消息)
    	SetTimer(hWnd,9999,1000,(TIMERPROC)timerProc);//调用定时器处理函数。
    }
    
    int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                         _In_opt_ HINSTANCE hPrevInstance,
                         _In_ LPWSTR    lpCmdLine,
                         _In_ int       nCmdShow)
    {
        UNREFERENCED_PARAMETER(hPrevInstance);
        UNREFERENCED_PARAMETER(lpCmdLine);
    
        // TODO: 在此处放置代码。
    
        // 初始化全局字符串
        LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
        LoadStringW(hInstance, IDC_WINDOWSPROJECT1, szWindowClass, MAX_LOADSTRING);
        MyRegisterClass(hInstance);
    
        // 执行应用程序初始化:
        if (!InitInstance (hInstance, nCmdShow))
        {
            return FALSE;
        }
    
        HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WINDOWSPROJECT1));
    
        MSG msg;
    
        // 主消息循环:
        while (GetMessage(&msg, nullptr, 0, 0))
        {
            if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);//广播函数:将消息发送给每一个窗口应用程序的消息处理函数
            }
        }
    
        return (int) msg.wParam;
    }
    
    
    
    //
    //  函数: MyRegisterClass()
    //
    //  目标: 注册窗口类。
    //
    ATOM MyRegisterClass(HINSTANCE hInstance)
    {
        WNDCLASSEXW wcex;
    
        wcex.cbSize = sizeof(WNDCLASSEX);
    
        wcex.style          = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
        wcex.lpfnWndProc    = WndProc;
        wcex.cbClsExtra     = 0;
        wcex.cbWndExtra     = 0;
        wcex.hInstance      = hInstance;
        wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WINDOWSPROJECT1));
        wcex.hCursor        = LoadCursor(nullptr, IDC_ARROW);
        wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
        wcex.lpszMenuName   = MAKEINTRESOURCEW(IDC_WINDOWSPROJECT1);
        wcex.lpszClassName  = szWindowClass;
        wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
    
        return RegisterClassExW(&wcex);
    }
    
    //
    //   函数: InitInstance(HINSTANCE, int)
    //
    //   目标: 保存实例句柄并创建主窗口
    //
    //   注释:
    //
    //        在此函数中,我们在全局变量中保存实例句柄并
    //        创建和显示主程序窗口。
    //
    BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
    {
       hInst = hInstance; // 将实例句柄存储在全局变量中
    
       HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
          CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
       g_hWnd = hWnd;
    
       if (!hWnd)
       {
          return FALSE;
       }
    
       ShowWindow(hWnd, nCmdShow);
       UpdateWindow(hWnd);
    
       return TRUE;
    }
    
    //
    //  函数: WndProc(HWND, UINT, WPARAM, LPARAM)
    //
    //  目标: 处理主窗口的消息。
    //
    //  WM_COMMAND  - 处理应用程序菜单
    //  WM_PAINT    - 绘制主窗口
    //  WM_DESTROY  - 发送退出消息并返回
    
    //
    //
    HDC g_hDc;
    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    	wchar_t buff[256];
        switch (message)
        {
    	
    
    	case WM_SIZE:
    		memset(buff, 0, 256 * 2);
    		wsprintf(buff, L"窗口大小改变:(w:%d h:%d)\n", HIWORD(lParam),LOWORD(lParam));
    		WriteConsole(g_hConsole, buff, wcslen(buff), NULL, NULL);
    		break;
    	
    	//键盘消息:
    	case WM_KEYDOWN:
    		memset(buff, 0, 256 * 2);
    		wsprintf(buff, L"按下 键值:0X %x\n", wParam);
    		WriteConsole(g_hConsole, buff, wcslen(buff), NULL, NULL);
    		break;
    	case WM_KEYUP:
    		memset(buff, 0, 256 * 2);
    		wsprintf(buff, L"弹起 键值:0X %x\n", wParam);
    		WriteConsole(g_hConsole, buff, wcslen(buff), NULL, NULL);
    		break;
    	case WM_SYSKEYDOWN:
    		memset(buff, 0, 256 * 2);
    		wsprintf(buff, L"按下系统按键 键值:0X %x\n", wParam);
    		WriteConsole(g_hConsole, buff, wcslen(buff), NULL, NULL);
    		break;
    	case WM_SYSKEYUP:
    		memset(buff, 0, 256 * 2);
    		wsprintf(buff, L"弹起系统按键 键值:0X %x\n", wParam);
    		WriteConsole(g_hConsole, buff, wcslen(buff), NULL, NULL);
    		break;
    
    
    	case WM_LBUTTONDOWN:
    		WriteConsole(g_hConsole, L"鼠标左键按下\n", wcslen(L"鼠标左键按下\n"), NULL, NULL);
    		break;
    	case WM_MOUSEWHEEL:
    		memset(buff, 0, 256 * 2);
    		wsprintf(buff, L"(%d,%d)滚动幅度:%d 键值:%0x%x\n", LOWORD(lParam), HIWORD(lParam),HIWORD(wParam),LOWORD(wParam));
    		//滚轮消息的wParam的高字节用来记录滚动的幅度,低字节记录按键
    		//lParam仍然记录鼠标的坐标
    		WriteConsole(g_hConsole, buff, wcslen(buff), NULL, NULL);
    		if (LOWORD(wParam) == MK_CONTROL && HIWORD(wParam) == 120)//MK_CONTROL代表按下了ctrl键并且向上滚动
    			WriteConsole(g_hConsole, L"放大\n", wcslen(L"放大\n"), NULL, NULL);
    		else if(LOWORD(wParam) == MK_CONTROL && HIWORD(wParam) != 120)
    			WriteConsole(g_hConsole, L"缩小\n", wcslen(L"缩小\n"), NULL, NULL);
    		break;
    	case WM_LBUTTONUP:
    		WriteConsole(g_hConsole, L"鼠标左键弹起\n", wcslen(L"鼠标左键弹起\n"), NULL, NULL);
    		break;
    	case WM_LBUTTONDBLCLK:
    		memset(buff, 0, 256 * 2);
    		wsprintf(buff, L"双击(%d,%d)\n", LOWORD(lParam), HIWORD(lParam));
    		MessageBox(hWnd, buff, L"双击", MB_OK);
    		
    		break;
    
    
    	
    	case WM_MOUSEMOVE: {
    		PAINTSTRUCT ps;
    		int x = LOWORD(lParam);
    		int y = HIWORD(lParam);
    		memset(buff, 0, 256 * 2);
    		wsprintf(buff, L"(%d,%d)\n", x, y);
    		WriteConsole(g_hConsole, buff, wcslen(buff), NULL, NULL);//写入数据到控制台
    		if (LOWORD(wParam)==MK_LBUTTON) {//如果鼠标左键按下,并且移动就画图
    			//g_hDc = GetDC(hWnd);//得到当前窗口应用程序的绘图设备句柄
    			//SetPixel(g_hDc, x, y, RGB(255, 0, 0));
    			//ReleaseDC(hWnd, g_hDc);
    
    			g_hDc=BeginPaint(hWnd, &ps);
    			SetPixel(g_hDc, x, y, RGB(255, 0, 0));
    			EndPaint(hWnd, &ps);
    
    
    		}
    
    
    	}//如果想要在switch case中定义变量需要一个大花括号括起来。
    		
    	
    	case WM_CREATE:
    			On_Create(hWnd, wParam, lParam);
    		break;
        case WM_COMMAND:
            {
                int wmId = LOWORD(wParam);
                // 分析菜单选择:
                switch (wmId)
                {
                case IDM_ABOUT:
                    DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                    break;
                case IDM_EXIT:
                    DestroyWindow(hWnd);
                    break;
                default:
                    return DefWindowProc(hWnd, message, wParam, lParam);
                }
            }
            break;
        case WM_PAINT:
            {
                PAINTSTRUCT ps;
                HDC hdc = BeginPaint(hWnd, &ps);//BeginPaint()函数返回绘图设备句柄
                // TODO: 在此处添加使用 hdc 的任何绘图代码...
    			Ellipse(hdc, 10, 10, 30, 30);//画一个圆形,左上角(10,10)右下角(30,30)
    			for (int i = 0; i < 256; i++) {
    				for (int j = 0; j < 256; j++) {
    		
    					SetPixel(hdc, i, j+i, RGB(i, j, 0));//画一个点,坐标(i,j)
    				}
    			}
                EndPaint(hWnd, &ps);
    			MessageBox(hWnd, L"重绘", L"提示", MB_OK);
            }
            break;
    	case WM_TIMER://定时器消息
    		memset(buff, 0, 265 * 2);
    		wsprintf(buff, L"定时器:%d,%d,%d,%d\n", LOWORD(lParam), HIWORD(lParam), LOWORD(wParam), HIWORD(wParam));
    		WriteConsole(g_hConsole, buff, wcslen(buff), NULL, NULL);
    		//SendMessage(hWnd, WM_PAINT, NULL, NULL);//向窗口发送WM_PAINT消息
    		RECT rect;
    		GetWindowRect(hWnd, &rect);//获取窗口客户区
    		InvalidateRect(hWnd, &rect,true);
    		break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        return 0;
    }
    
    // “关于”框的消息处理程序。
    INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
    {
        UNREFERENCED_PARAMETER(lParam);
        switch (message)
        {
        case WM_INITDIALOG:
            return (INT_PTR)TRUE;
    
        case WM_COMMAND:
            if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
            {
                EndDialog(hDlg, LOWORD(wParam));
                return (INT_PTR)TRUE;
            }
            break;
        }
        return (INT_PTR)FALSE;
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值