• 9.windows消息机制(四)


    1.绘图消息

      WM_PAINT - 当窗口需要绘制的时候,会发送窗口处理函数。

      需要重新绘制的情况:

        (1)窗口从创建到第一次显示

        (2)从被遮挡到重新显示

        (3)窗口变大(窗口变小时,窗口本身不需要重新,但如果注册窗口类中加了CS_HREDRAW | CS_VREDRAW风格,就会重绘) 

        (4)调用InvalidateRect函数  

      窗口无效区域 - 被声明成需要重新绘制的区域。

      BOOL InvalidateRect( HWND              hWnd,    //窗口句柄

                                        CONST RECT*   lpRect,    //区域的矩形坐标

                                        BOOL               bErase);  //重回前是否擦除

      在程序中,如果需要绘制窗口,调用函数声明窗口无效区域。

      wPARAM - 不使用

      lPARAM - 不使用

      消息处理步骤

        (1)开始绘图处理

           HDC BeginPaint( HWND  hWnd,  //绘图窗口

                                            LPPAINTSTRUCT  lpPaint);  //绘图参数的buffer

           返回绘图设备句柄HDC

        (2)绘图

        (3)结束绘图

           BOOL EndPaint( HWND  hWnd,  //绘图窗口

                                            CONST PAINTSTRUCT  *lpPaint);  //绘图参数的指针

    2.键盘消息

      WM_KEYDOWN - 按键被按下时产生

      WM_KEYUP - 按键被放开时产生

      WM_SYSKEYDOWN - 系统键按下时产生,比如ALT、F10

      WM_SYSKEYUP - 系统键放开时产生

      WM_CHAR - 字符消息(TranslateMessage发送的)

      消息参数:

        按键消息:wPARAM - 按键的Virtual Key(虚拟键码)(无法区分大小写,所以可见字符需要翻译)

                              lPARAM - 按键的参数,比如按下次数

        WM_CHAR消息:wPARAM - 输入的字符(ASC字符编码)

                       lPARAM - 按键的相关参数

      TranslateMessage(&nMsg)内部的大致处理过程:

      {

        检查是否是键盘消息

        if ( nMsg.message != WM_KEYDOWN ) { return ; }

        else

        {

          通过nMsg.wParam(虚拟键码)可以判断是否是可见字符的按键被按下

          if (不是)  { return ; }

          else

          {

            判断CapsLock(大写锁定键是否处于打开状态)

            if (关闭)  {  PostMessage(nMsg.hWnd, WM_CHAR, 小写字母ASC码, ...);  }

            else  {  PostMessage(nMsg.hWnd, WM_CHAR, 大写字母ASC码, ...);  }

          }

        }

      }

      消息的使用

      (1)KEYDOWN可以重复出现,KEYUP只能在按键松开时出现一次。

      (2)TranslateMessage在转换WM_KEYDOWN消息时,对于可见字符产生WM_CHAR,不可见字符无此消息。

      (3)WM_KEYDOWN/UP的wParam表示按键的虚拟键码值,WM_CHAR的wParam表示字符的ASC编码值。

      下面是相关代码:

    #include "stdafx.h"
    #include <stdio.h>
    
    HINSTANCE g_hInstance = 0;  //接收当前程序实例句柄
    HANDLE g_hOutput = 0;  //接收标准输出句柄
    
    void OnPaint(HWND hWnd)
    {
        char szText[] = "WM_PAINT
    ";
        //WriteConsole(g_hOutput, szText, strlen(szText), NULL, NULL);
        /*****************绘图********************/
        PAINTSTRUCT ps = { 0 };
        HDC hdc = BeginPaint(hWnd, &ps);
        TextOut(hdc, 100, 100, "hello", strlen("hello"));
        EndPaint(hWnd, &ps);
        /*******必须放在WM_PAINT的消息处理调用中*****/
    }
    void OnKeyDown(HWND hWnd, WPARAM wParam)
    {
        char szText[256] = { 0 };
        sprintf_s(szText, "WM_KEYDOWN:%08x
    ", wParam);
        WriteConsole(g_hOutput, szText, strlen(szText), NULL, NULL);
    }
    void OnKeyUp(HWND hWnd, WPARAM wParam)
    {
        char szText[256] = { 0 };
        sprintf_s(szText, "WM_KEYUP:%08x
    ", wParam);
        WriteConsole(g_hOutput, szText, strlen(szText), NULL, NULL);
    }
    void OnChar(HWND hWnd, WPARAM wParam)
    {
        char szText[256] = { 0 };
        sprintf_s(szText, "WM_CHAR:%08x
    ", wParam);
        WriteConsole(g_hOutput, szText, strlen(szText), NULL, NULL);
    }
    //窗口处理函数
    LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        switch (msg)
        {
        case WM_CHAR:
            OnChar(hWnd, wParam);
            break;
        case WM_KEYDOWN:
            OnKeyDown(hWnd, wParam);
            break;
        case WM_KEYUP:
            OnKeyUp(hWnd, wParam);
            break;
        case WM_LBUTTONDOWN:
            InvalidateRect(hWnd, NULL, TRUE);
            break;
        case WM_PAINT:
            OnPaint(hWnd);
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        }
        return DefWindowProc(hWnd, msg, wParam, lParam);
    }
    //注册窗口类
    BOOL Register(LPSTR lpClassName, WNDPROC wndProc)
    {
        WNDCLASSEX wce = { 0 };
    
        wce.cbSize = sizeof(wce);
        wce.cbClsExtra = 200;
        wce.cbClsExtra = 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;  //窗口水平或垂直发生变化时,重新绘制
    
        ATOM nAtom = RegisterClassEx(&wce);
        if (0 == nAtom)
        {
            return FALSE;
        }
        return TRUE;
    }
    //创建主窗口
    HWND CreateMainWindow(LPSTR lpClassName, LPSTR lpWndName)
    {
        HWND hWnd = CreateWindowEx(0, lpClassName, lpWndName, WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
            NULL, NULL, g_hInstance, NULL);
        return hWnd;
    }//显示窗口
    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, LPTSTR lpCmdLine, int nCmdShow)
    {
        AllocConsole();
        g_hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    
        g_hInstance = hInstance;
        Register("Main", WndProc);
        HWND hWnd = CreateMainWindow("Main", "window");
        Display(hWnd);
        Message();
    
        return 0;
    }
    View Code
  • 相关阅读:
    WPF数据绑定机制是如何实现
    C#自定义特性的使用
    MVVMLight学习笔记(一)---MVVMLight概述
    C# Autofac学习笔记
    EFCodeFirst快速搭建入门
    SQL having与where用法区别
    EventWaitHandle 类
    C# EF 使用 (CodeFirst模式)
    wmi 远程启动程序
    Centos 7 的一些 基础知识
  • 原文地址:https://www.cnblogs.com/csqtech/p/5596388.html
Copyright © 2020-2023  润新知