您的位置:首页 > 编程语言

走进windows编程的世界-----消息处理函数(3)

2014-07-07 16:04 453 查看
二 定时器消息 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结束定时器/* File : winpaint.cpp
* Auth : sjin
* Date : 20140706
* Mail : 413977243@qq.com
*/

#include <Windows.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 )
{
/*
UINT SetTimer( HWND hWnd, //窗口的句柄,可以为NULL UINT nIDEvent,//定时器的ID,0为不预设ID UINT uElapse,//定时器时间间隔,毫秒级别 TIMERPROC lpTimerFunc );//定时器的处理函数,可以为NULL

return : 创建好的定时器的ID号
*/
//使用窗口处理函数,创建2个定时器
SetTimer( hWnd, 1000, 3 * 1000, NULL );
SetTimer( hWnd, 1001, 5 * 1000, NULL );
//使用窗口处理函数, 未指明定时器ID
g_nTimerID1 = SetTimer( hWnd, 0, 2* 1000, NULL );
//使用TimerProc处理函数创建定时器
//SetTimer( hWnd, 1002, 7 * 1000, TimerProc1 );
SetTimer( hWnd, 1002, 7 * 1000, NULL );
}

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;
case 1002:/*1002 设置相应的处理函数,不会在这里调用*/
{
CHAR szText[] = "1002: 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:
/*销毁定时器
BOOL KillTimer( HWND hWnd,//窗口句柄 UINT uIDEvent );//定时器ID
*/
KillTimer( hWnd, 1000 );
KillTimer( hWnd, 1001 );
KillTimer( hWnd, 1002 );
KillTimer( hWnd, g_nTimerID1 );
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);
CHAR szText[] = "Debug Message......:\n";
/*将szText 写到控制台*/
WriteConsole(g_hStdOut, szText, strlen(szText), NULL, NULL);
}

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 - 可以设置更多信息/* File : winMenu.cpp
* Auth : sjin
* Date : 20140706
* Mail : 413977243@qq.com
*/

#include <Windows.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( );
//增加菜单项 (&N) 增加快捷键ALT+N)
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_SEPARATOR, 0, NULL );
AppendMenu( hEditMenu, MF_STRING, 1004, "拷贝(&C)" );
/*增加分割线的标示*/
AppendMenu( hEditMenu, MF_SEPARATOR, 0, NULL );
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_SEPARATOR, 0, NULL );
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 )
{
/*wParam: HIWORD: 通知消息的标示
* LOWORD:菜单项的ID
* lParam: 控件的句柄
* 对菜单来说这个为NULL
* 对其他控件(按钮等)为句柄
*/
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是一个API函数,功能是复选或撤消复选指定的菜单条目*/
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;

/*用户点击菜单、按钮控件等时,系统会想窗口发送WM_COAMMD消息*/
case WM_COMMAND:
OnCommand( hWnd, nMsg, wParam, lParam );
break;

/*用户点击菜单,显示弹出菜单之前,系统会向窗口发送WM_INITMENUPOPUP消息
*用于更新菜单项的状态
*/
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_MENU" );
HWND hWnd = CreateWnd( "MYWND_MENU" );
DisplayWnd( hWnd );
Message( );
return 0;
}三 系统菜单  1 执行系统提供的窗口命令,例如最大化、关闭等命令。本质上和普通菜单一样,所以我们也可以在程序中使用这个菜单
    
  2 系统菜单的使用
    2.1 获取系统菜单
       GetSystemMenu
HMENU GetSystemMenu(
HWND hWnd, //要获取的窗口句柄
BOOL bRevert  //获取时重置标示
);
    bRevert: TRUE 重置 FLASE 不重置
    当Revert为TRUE时,会将菜单重新置成默认的状态,并返回菜单句柄。如果为FALSE,菜单项不重置,获取到当前系统菜单的状态。
    
    2.2 修改系统菜单,例如增加、删除
       2.2.1 AppednMenu
       2.2.2 InsertMenu 
         比AppednMenu增加了一个插入菜单项的位置或ID。
       2.2.3 删除菜单项
BOOL RemoveMenu( //
HMENU hMenu, //菜单句柄
UINT uPosition,//菜单项的位置或ID
UINT uFlags );//菜单项的位置或ID的标示。
    uFlags为MF_BYCOMMAND, uPosition为菜单ID
    uFlags为MF_BYPOSITION,uPosition为菜单位置    2.3 系统菜单的命令响应
       系统菜单的命令响应,是在WM_SYSCOMMAND中。
       WPARAM - LOWORD(wParam)为增加的菜单的ID
int nID = LOWORD( wParam );
switch( nID )
{
case 1001:
//...
break;
}

/* File : winMenu.cpp
* Auth : sjin
* Date : 20140706
* Mail : 413977243@qq.com
*/

#include <Windows.h>
#include <stdio.h>

HINSTANCE g_hInst   = NULL;
HANDLE    g_hStdOut = NULL;

void OnCreate( HWND hWnd, UINT nMsg,
WPARAM wParam, LPARAM lParam )
{
/* 获取系统菜单
* HMENU GetSystemMenu(
*    HWND hWnd, //要获取的窗口句柄
*    BOOL bRevert  //获取时重置标示
*   );
*   bRevert : TRUE时,菜单会重置为默认状态
*             FALSE: 菜单不重置获得当前系统的菜单状态
*/
HMENU hSysMenu = GetSystemMenu( hWnd, FALSE );
/*删除菜单项
* BOOL RemoveMenu( //
*		 HMENU hMenu, //菜单句柄
*       UINT uPosition,//菜单项的位置或ID
*        UINT uFlags );//菜单项的位置或ID的标示
*   uFlags为MF_BYCOMMAND, uPosition为菜单ID
*   uFlags为MF_BYPOSITION,uPosition为菜单位置
*/
RemoveMenu( hSysMenu, 0, MF_BYPOSITION );
RemoveMenu( hSysMenu, 0, MF_BYPOSITION );
RemoveMenu( hSysMenu, 0, MF_BYPOSITION );
RemoveMenu( hSysMenu, 0, MF_BYPOSITION );
RemoveMenu( hSysMenu, 0, MF_BYPOSITION );
// 增加菜单项
InsertMenu( hSysMenu, 0, MF_BYPOSITION|MF_STRING,
1001, "测试1" );
InsertMenu( hSysMenu, 1, MF_BYPOSITION|MF_STRING,
1002, "测试2" );
}

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

int nID = LOWORD( wParam );
switch( nID )
{
case 1001:
MessageBox( NULL, "Hello 1001", "SysMenu", MB_CANCELTRYCONTINUE );
break;
case 1002:
MessageBox( NULL, "Hello 1002",  "SysMenu", MB_OK );
break;
default:
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_SYSCOMMAND:/*系统菜单命令响应*/
OnSysCommand( 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_HREDRAW|CS_VREDRAW;

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息