Win32编程day05 学习笔记

一 鼠标消息

  1 鼠标消息
    1) 基本鼠标消息
    WM_LBUTTONDOWN   左键按下
    WM_LBUTTONUP     左键抬起
    WM_RBUTTONDOWN   右键按下
    WM_RBUTTONUP     右键抬起
    WM_MOUSEMOVE     鼠标移动
    2) 双击消息
    WM_LBUTTONDBLCLK 左键双击
    WM_RBUTTONDBLCLK 右键双击
    3) 滚轮消息
    WM_MOUSEWHEEL    鼠标滚轮

  2 消息的参数
    WPARAM - 当前键盘和鼠标按键状态,例如MK_CONTROL/MK_SHIFT,MK_LBUTTON等
    LPARAM - 当前鼠标的坐标,坐标的原点是窗口客户区的左上角.
       X坐标 - LOWORD(lParam),低16位
       Y坐标 - HIWORD(lParam),高16位
    参数具体内容和具体鼠标消息有稍微不同.
   
  3 消息的使用
 
    3.1 基本鼠标消息,只需在窗口处理函数增加消息处理即可. 当消息来临,获取鼠标和按键状态.例如:

case WM_MOUSEMOVE:
{
    int nX = LOWORD(lParam);
    int nY = HIWORD(lParam);
}

    附:坐标转换的函数 ClientToScreen可以将鼠标坐标转换为屏幕的坐标.

   3.2 双击消息
   3.2.1 窗口注册要增加 CS_DBLCLKS 类型
    wce.style = CS_DBLCLKS|...;
   3.2.2 在窗口处理函数中增加消息处理
   3.2.3 产生过程,例如:WM_LBUTTONDBLCLK
      WM_LBUTTONDOWN
      WM_LBUTTONUP
      WM_LBUTTONDBLCLK
      WM_LBUTTONUP
      连续两次LBUTTONDOWN的时间间隔小于预定的双击时间间隔,就会产生LBUTTONDBLCLK消息.
      双击时间间隔可以通过控制面板调整.

 3.3 滚轮消息
  3.3.1 由于WM_MOUSEWHEEL需要Winnt4.0以上版本支持,所以需要包含在windows.h的头文件前,增加 _WIN32_WINNT 宏定义,
        #define _WIN32_WINNT 0x0400
    3.3.2 在窗口处理函数中增加消息处理
    3.3.3 参数
     LPARAM 与其它鼠标消息类同
     WPARAM - LOWORD(WPARAM) 表示按键状态
              HIWORD(WPARAM) 滚轮滚动幅度,
                120的倍数,可以为正负值.
        正值: 滚轮向上滚动, 一般窗口向上滚动
        负值: 滚轮向下滚动, 一般窗口向下滚动

View Code
// winmouse.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "stdio.h"

int g_nXPos = 0;
int g_nYPos = 0;
int g_nX1Rect = 0;
int g_nY1Rect = 0;
int g_nX2Rect = 0;
int g_nY2Rect = 0;

HINSTANCE g_hInst   = NULL;
HANDLE    g_hStdOut = NULL;

void PrintLog(LPSTR lpszLog)
{
    WriteConsole(g_hStdOut, lpszLog, strlen(lpszLog), NULL, NULL);
}

void OnPaint(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
    PAINTSTRUCT ps = {0};
    HDC hDC = BeginPaint(hWnd, &ps);
    CHAR szText[] = "Hello Mouse";
    TextOut(hDC, g_nXPos, g_nYPos, szText, strlen(szText));

    Rectangle(hDC, g_nX1Rect, g_nY1Rect, g_nX2Rect, g_nY2Rect);
    EndPaint(hWnd, &ps);
}

LRESULT CALLBACK WndProc( HWND hWnd,
                          UINT nMsg,
                          WPARAM wParam,
                          LPARAM lParam )
{
    switch( nMsg )
    {
    case WM_PAINT:
        OnPaint(hWnd, nMsg, wParam, lParam); break;
    case WM_LBUTTONDOWN:
        {
            PrintLog("WM_LBUTTONDOWN\n");
            g_nX1Rect = LOWORD(lParam);
            g_nY1Rect = HIWORD(lParam);
        }
        break;
    case WM_LBUTTONUP:
        {
            PrintLog("WM_LBUTTONUP\n");
            g_nX2Rect = LOWORD(lParam);
            g_nY2Rect = HIWORD(lParam);
            InvalidateRect(hWnd, NULL, TRUE);
        }
        break;
    case WM_RBUTTONDOWN:
        PrintLog("WM_RBUTTONDOWN\n");
        break;
    case WM_RBUTTONUP:
        PrintLog("WM_RBUTTONUP\n");
        break;
    case WM_MOUSEMOVE:
        {
            int nX = LOWORD(lParam);
            int nY = HIWORD(lParam);
            POINT ptScreen = {0};
            ptScreen.x = nX;
            ptScreen.y = nY;
            ClientToScreen(hWnd, &ptScreen);

            CHAR szText[260] = { 0 };
            sprintf( szText, 
                "WM_MOUSEMOVE: X=%d(%d),Y=%d(%d)\n",
                nX, ptScreen.x, nY, ptScreen.y );
            PrintLog( szText );
            if( wParam & MK_CONTROL )
            {
                PrintLog( "WM_MOUSEMOVE: MK_CONTROL\n" );
            }
            if( wParam & MK_LBUTTON )
            {
                PrintLog( "WM_MOUSEMOVE: MK_LBUTTON\n" );
            }

            g_nXPos = LOWORD(lParam);
            g_nYPos = HIWORD(lParam);
            InvalidateRect( hWnd, NULL, TRUE );
        }
        break;
    case WM_LBUTTONDBLCLK:
        PrintLog( "WM_LBUTTONDBLCLK\n" );
        break;
    case WM_RBUTTONDBLCLK:
        PrintLog( "WM_RBUTTONDBLCLK\n" );
        break;
    case WM_MOUSEWHEEL:
        {
            short nDelta = HIWORD(wParam);
            int nX = LOWORD(lParam);
            int nY = HIWORD(lParam);
            CHAR szText[260] = { 0 };
            sprintf( szText, 
                "WM_MOUSEWHEEL: Detla=%d, X=%d,Y=%d\n",
                nDelta, nX, nY );
            PrintLog( szText );
        }
        break;
    case WM_DESTROY:
        PostQuitMessage( 0 );
        break;
    }
    return DefWindowProc( hWnd, nMsg,
        wParam, lParam );
}

BOOL RegisterWnd( LPSTR pszClassName )
{
    WNDCLASSEX wce = { 0 };
    wce.cbSize          = sizeof( wce );
    wce.cbClsExtra      = 0;
    wce.cbWndExtra    = 0;
    wce.hbrBackground = HBRUSH(COLOR_WINDOW);
    wce.hCursor          = NULL;
    wce.hIcon          = NULL;
    wce.hIconSm       = NULL;
    wce.hInstance      = g_hInst;
    wce.lpfnWndProc   = WndProc;
    wce.lpszClassName = pszClassName;
    wce.lpszMenuName  = NULL;
    wce.style         = CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS;
    ATOM nAtom = RegisterClassEx( &wce );
    if( 0 == nAtom )
    {
        return FALSE;
    }
    return TRUE;
}

HWND CreateWnd( LPSTR pszClassName )
{
    HWND hWnd = CreateWindowEx( 0,
        pszClassName, "MyWnd", 
        WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
        CW_USEDEFAULT, CW_USEDEFAULT, 
        CW_USEDEFAULT, NULL, NULL, 
        g_hInst, NULL );
    return hWnd;
}

void DisplayWnd( HWND hWnd )
{
    ShowWindow( hWnd, SW_SHOW );
    UpdateWindow( hWnd );
}

void Message( )
{
    MSG msg = { 0 };
    while( GetMessage( &msg, NULL, 0, 0 ) )
    {
        TranslateMessage( &msg );
        DispatchMessage( &msg );
    }
}

void NewConsole( )
{
    AllocConsole( );
    g_hStdOut = 
        GetStdHandle( STD_OUTPUT_HANDLE );
}

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
     NewConsole( );
     g_hInst = hInstance;
    RegisterWnd( "MyWnd" );
    HWND hWnd = CreateWnd( "MyWnd" );
    DisplayWnd( hWnd );
    Message( );

    return 0;
}

二 定时器消息

 1 定时器消息 WM_TIMER
   按照定时器设置时间段,自动向窗口发送一个定时器消息WM_TIMER. 优先级比较低.
   定时器精度比较低,毫秒级别.消息产生时间也精度比较低.
  
 2 消息和函数
   2.1 WM_TIMER  - 消息ID
    wParam: 定时器的ID
    lParam: 定时器的处理函数

   2.2 SetTimer  - 设置一个定时器

UINT SetTimer(
HWND hWnd, //窗口的句柄,可以为NULL
UINT nIDEvent,//定时器的ID,0为不预设ID
UINT uElapse,//定时器时间间隔,毫秒级别
TIMERPROC lpTimerFunc );//定时器的处理函数,可以为NULL

   返回一个创建好的定时器ID

  2.3 KillTimer - 结束一个定时器

BOOL KillTimer(
      HWND hWnd,//窗口句柄
      UINT uIDEvent );//定时器ID

  2.4 TimerProc - 定时器处理函数

VOID CALLBACK TimerProc(
    HWND hwnd, //窗口句柄
    UINT uMsg, //WM_TIMER消息ID
    UINT idEvent,//定时器ID
    DWORD dwTime   );//当前系统时间

  3 使用方式
    3.1 创建定时器 SetTimer
     3.1.1 指定窗口句柄HWND,那么 TIMERPROC 参数可以为空,那么WM_TIMER消息将会发送给指定窗口. 如果未指定, TIMERPROC不能空, 必须指定定时器处理程序.
     3.1.2 如果指定定时器ID,SetTimer会按照这个ID创建定时器, 如果未指定,会返回一个创建定时器ID.

nTimerID = SetTimer( NULL, 0, 7 * 1000,TimerProc1 );

    3.2 处理消息
      可以根据消息传入定时器ID号,分别处理.
    3.3 结束定时器
      在不使用时, KillTimer结束定时器.

KillTimer( hWnd, 1000 );
View Code
// WinTimer.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "stdio.h"

HINSTANCE g_hInst   = NULL;
HANDLE    g_hStdOut = NULL;
UINT      g_nTimerID1 = 0;

void CALLBACK TimerProc1( HWND hWnd,
                          UINT nMsg,
                          UINT idEvent,
                          DWORD dwTime )
{
    CHAR szText[] = "TimerProc1: Hello Timer\n";
    WriteConsole( g_hStdOut, szText,
        strlen(szText), NULL, NULL );
}

void OnCreate( HWND hWnd, UINT nMsg,
    WPARAM wParam, LPARAM lParam )
{
    //使用窗口处理函数,创建2个定时器
    SetTimer( hWnd, 1000, 3 * 1000, NULL );    
    SetTimer( hWnd, 1001, 5 * 1000, NULL );
    //使用窗口处理函数, 未指明定时器ID
    g_nTimerID1 = SetTimer( hWnd, 0, 
        1 * 1000, NULL );
    //使用TimerProc处理函数创建定时器
    SetTimer( hWnd, 1002, 7 * 1000, TimerProc1 );
}

void OnTimer( HWND hWnd, UINT nMsg,
    WPARAM wParam, LPARAM lParam )
{
    switch( wParam )
    {
    case 1000:
        {
            CHAR szText[] = "1000: Hello Timer\n";
            WriteConsole( g_hStdOut, szText,
                strlen(szText), NULL, NULL );
        }
        break;
    case 1001:
        {
            CHAR szText[] = "1001: Hello Timer\n";
            WriteConsole( g_hStdOut, szText,
                strlen(szText), NULL, NULL );
        }
        break;
    default:
        {
            CHAR szText[260] = {0};
            sprintf( szText, "%d: Hello Timer\n",
                g_nTimerID1 );
            WriteConsole( g_hStdOut, szText,
                strlen(szText), NULL, NULL );
        }
        break;
    }
}

LRESULT CALLBACK WndProc( HWND hWnd,
                          UINT nMsg,
                          WPARAM wParam,
                          LPARAM lParam )
{
    switch( nMsg )
    {
    case WM_CREATE:
        OnCreate( hWnd, nMsg, wParam, lParam );
        break;
    case WM_TIMER:
        OnTimer( hWnd, nMsg, wParam, lParam );
        break;
    case WM_DESTROY:
        KillTimer( hWnd, 1000 );
        PostQuitMessage( 0 );
        return 0;
    }
    return DefWindowProc( hWnd, nMsg,
        wParam, lParam );
}

BOOL RegisterWnd( LPSTR pszClassName )
{
    WNDCLASSEX wce = { 0 };
    wce.cbSize        = sizeof( wce );
    wce.cbClsExtra    = 0;
    wce.cbWndExtra    = 0;
    wce.hbrBackground = HBRUSH(COLOR_WINDOW);
    wce.hCursor       = NULL;
    wce.hIcon          = NULL;
    wce.hIconSm       = NULL;
    wce.hInstance     = g_hInst;
    wce.lpfnWndProc   = WndProc;
    wce.lpszClassName = pszClassName;
    wce.lpszMenuName  = NULL;
    wce.style         = CS_VREDRAW|CS_HREDRAW;

    ATOM nAtom = RegisterClassEx( &wce );
    if( 0 == nAtom )
    {
        return FALSE;
    }
    return TRUE;
}

HWND CreateWnd( LPSTR pszClassName )
{
    HWND hWnd = CreateWindowEx( 0,
        pszClassName, "MyWnd", 
        WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
        CW_USEDEFAULT, CW_USEDEFAULT,
        CW_USEDEFAULT, NULL, NULL, 
        g_hInst, 0 );
    return hWnd;
}

void DisplayWnd( HWND hWnd )
{
    ShowWindow( hWnd, SW_SHOW );
    UpdateWindow( hWnd );
}

void Message( )
{
    MSG msg = {0};
    while ( GetMessage( &msg, NULL, 0, 0 ) )
    {
        TranslateMessage( &msg );
        DispatchMessage( &msg );
    }
}

void NewConsole( )
{
    AllocConsole( );
    g_hStdOut = 
        GetStdHandle( STD_OUTPUT_HANDLE );
}

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
    NewConsole( );
    g_hInst = hInstance;
    RegisterWnd( "MYWND" );
    HWND hWnd = CreateWnd( "MYWND" );
    DisplayWnd( hWnd );
    Message( );
    return 0;
}

三 菜单
  1 菜单基础
    菜单 - 每个菜单会有一个HMENU句柄
    菜单项 - 每个菜单项会有一个ID号,可以根据这个ID执行不同的操作
  2 菜单的使用
    2.1 菜单创建
      2.1.1 CreateMenu - MENU 菜单
      2.1.2 CreatePopupMenu - POPUPMENU 弹出式菜单
      2.1.3 AppenedMenu - 增加菜单项

  BOOL AppendMenu(
  HMENU hMenu, //菜单句柄
  UINT uFlags, //菜单项标示
  UINT uIDNewItem, //菜单项的ID或者子菜单句柄
  LPCTSTR lpNewItem ); //菜单项的名称

    uFlags:
      MF_STRING - lpNewItem是一个字符串
      MF_POPUP  - uIDNewItem是一个子菜单句柄
      MF_SEPARATOR - 增加分隔项
      MF_CHECKED/MF_UNCHECKED - 设置和取消菜单项的对勾
      MF_DISABLED/MF_ENABLE - 菜单项禁止和允许状态
   2.2 菜单的命令响应
     2.2.1 WM_COMMAND消息
       当用户点击菜单、按钮控件等时,系统会向窗口发送WM_COAMMD消息。
         WPARAM:HIWORD - 通知消息标识
                 LOWORD - 菜单项的ID号
         LPARAM:控件的句柄
     2.2.2 命令处理
        根据菜单项的ID号作相应处理。
       
   2.3 菜单项的状态
      2.3.1 WM_INITMENUPOPUP消息
        当用户点击菜单,显示弹出菜单之前,系统会向窗口发送WM_INITMENUPOPUP消息。
        WPARAM:是菜单句柄
        LPARAM:LOWORD - 菜单位置
                HIWORD - 是否是系统菜单
      2.3.2 命令处理
        根据WPARAM的菜单句柄,使用MenuAPI函数,修改菜单状态。
         CheckMenuItem - 选择
         EnableMenuItem - 允许和禁止
         SetMenuItemInfo - 可以设置更多信息

View Code
// WinMenu.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "stdio.h"

HINSTANCE g_hInst   = NULL;
HANDLE    g_hStdOut = NULL;
BOOL      g_bCheckCut = FALSE;

void OnCreate( HWND hWnd, UINT nMsg,
    WPARAM wParam, LPARAM lParam )
{    //创建主菜单
    HMENU hMainMenu = CreateMenu( );
    //创建子菜单
    HMENU hFileMenu = CreatePopupMenu( );
    //增加菜单项
    AppendMenu( hFileMenu, MF_STRING|MF_CHECKED, 1001, "新建(&N)");
    AppendMenu( hFileMenu, MF_SEPARATOR, 0, NULL );
    AppendMenu( hFileMenu, MF_STRING, 1002, "退出(&X)");
    AppendMenu( hMainMenu, MF_STRING|MF_POPUP, 
        (UINT)hFileMenu, "文件(&F)");

    HMENU hEditMenu = CreatePopupMenu( );
    AppendMenu( hEditMenu, MF_STRING, 1003, "剪切(&T)" );
    AppendMenu( hEditMenu, MF_STRING, 1004, "拷贝(&C)" );
    AppendMenu( hEditMenu, MF_STRING, 1005, "粘贴(&P)" );
    AppendMenu( hMainMenu, MF_STRING|MF_POPUP, 
        (UINT)hEditMenu, "编辑(&E)");

    HMENU hHelpMenu = CreatePopupMenu( );
    AppendMenu( hHelpMenu, MF_STRING, 1006, "帮助(&H)" );
    AppendMenu( hHelpMenu, MF_STRING, 1007, "关于(&A)" );
    AppendMenu( hMainMenu, MF_STRING|MF_POPUP, 
        (UINT)hHelpMenu, "帮助(&H)");
    //给窗口设置主菜单
    SetMenu( hWnd, hMainMenu );
}

void OnCommand( HWND hWnd, UINT nMsg, 
               WPARAM wParam, LPARAM lParam )
{
    UINT nID = LOWORD( wParam );
    CHAR szText[260] = {0};
    sprintf( szText, "OnCommand: %d\n",
        nID );
    WriteConsole( g_hStdOut, szText,
        strlen(szText), NULL, NULL );
    switch( nID )
    {
    case 1002:
        PostQuitMessage( 0 );
        break;
    case 1003:
        g_bCheckCut = !g_bCheckCut;
        break;
    }
}

void OnInitMenuPopup( HWND hWnd, UINT nMsg,
    WPARAM wParam, LPARAM lParam )
{
    CHAR szText[260] = { 0 };
    sprintf( szText, 
        "OnInitMenuPopup: WPARAM=%08X, LPARAM=%08X\n", 
        wParam, lParam );
    WriteConsole( g_hStdOut, szText,
        strlen(szText), NULL, NULL );

    HMENU hMenu = (HMENU)wParam;
    if( TRUE == g_bCheckCut )
    {
        CheckMenuItem( hMenu, 1003, 
            MF_CHECKED|MF_BYCOMMAND );
    }
    else
    {
        CheckMenuItem( hMenu, 1003, 
            MF_UNCHECKED|MF_BYCOMMAND );
    }
}

LRESULT CALLBACK WndProc( HWND hWnd,
                          UINT nMsg,
                          WPARAM wParam,
                          LPARAM lParam )
{
    switch( nMsg )
    {
    case WM_CREATE:
        OnCreate( hWnd, nMsg, wParam, lParam );
        break;
    case WM_COMMAND:
        OnCommand( hWnd, nMsg, wParam, lParam );
        break;
    case WM_INITMENUPOPUP:
        OnInitMenuPopup( hWnd, nMsg, wParam, lParam );
        break;
    case WM_DESTROY:
        PostQuitMessage( 0 );
        return 0;
    }
    return DefWindowProc( hWnd, nMsg,
        wParam, lParam );
}

BOOL RegisterWnd( LPSTR pszClassName )
{
    WNDCLASSEX wce = { 0 };
    wce.cbSize        = sizeof( wce );
    wce.cbClsExtra    = 0;
    wce.cbWndExtra    = 0;
    wce.hbrBackground = HBRUSH(COLOR_WINDOW);
    wce.hCursor       = NULL;
    wce.hIcon          = NULL;
    wce.hIconSm       = NULL;
    wce.hInstance     = g_hInst;
    wce.lpfnWndProc   = WndProc;
    wce.lpszClassName = pszClassName;
    wce.lpszMenuName  = NULL;
    wce.style         = CS_VREDRAW|CS_HREDRAW;

    ATOM nAtom = RegisterClassEx( &wce );
    if( 0 == nAtom )
    {
        return FALSE;
    }
    return TRUE;
}

HWND CreateWnd( LPSTR pszClassName )
{
    HWND hWnd = CreateWindowEx( 0,
        pszClassName, "MyWnd", 
        WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
        CW_USEDEFAULT, CW_USEDEFAULT,
        CW_USEDEFAULT, NULL, NULL, 
        g_hInst, 0 );
    return hWnd;
}

void DisplayWnd( HWND hWnd )
{
    ShowWindow( hWnd, SW_SHOW );
    UpdateWindow( hWnd );
}

void Message( )
{
    MSG msg = {0};
    while ( GetMessage( &msg, NULL, 0, 0 ) )
    {
        TranslateMessage( &msg );
        DispatchMessage( &msg );
    }
}

void NewConsole( )
{
    AllocConsole( );
    g_hStdOut = 
        GetStdHandle( STD_OUTPUT_HANDLE );
}

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
    NewConsole( );
    g_hInst = hInstance;
    RegisterWnd( "MYWND" );
    HWND hWnd = CreateWnd( "MYWND" );
    DisplayWnd( hWnd );
    Message( );
    return 0;
}

 

posted @ 2012-08-12 15:16  唐小喵  阅读(719)  评论(0编辑  收藏  举报