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\n";
    //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\n", 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\n", 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\n", 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

 

posted @ 2016-06-18 16:25  甩锅侠  阅读(368)  评论(0)    收藏  举报