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

二 定时器消息

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 : [email protected]
 */  

#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 : [email protected]
 */    

#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;
}

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

时间: 2024-10-24 23:42:18

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

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

Win32消息机制 过程驱动:程序是按照我们预先定义好的顺序执行,每执行一步,下一步都已经按照预定的顺序 继续执行,直至程序结束. 事件驱动:程序的执行顺序是无序的.某个时间点所执行的代码,是由外界 通知.由于我们无法决定程序执行顺序.所以代码的执行也是无序的. Win32基本消息 WM_DESTROY:       窗口销毁时的消息,可以做退出或善后处理 WM_CREATE:       窗口创建消息,是在窗口创建后,窗口处理函数收到的第一条消息   可以在这个消息内,做初始化或者穿件子窗口

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

一 右键菜单  1 右键菜单    当在窗口点击鼠标右键时,弹出的菜单.  2 右键菜单的使用    2.1 创建菜单      CreatePopupMenu    2.2 菜单增加     AppendMenu    2.3 菜单的显示. BOOL TrackPopupMenu( HMENU hMenu, //显示的菜单句柄 UINT uFlags, //显示的方式 int x, //菜单的X屏幕坐标 int y, //菜单的Y屏幕坐标 int nReserved, //保留,必须为0 HW

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

一 WM_PAINT消息 1 WM_PAINT的产生   由于窗口的互相覆盖等,产生需要绘制的区域,那么会产生WM_PAINT消息.   一般情况下,不直接发送WM_PAINT消息,通过API声明需要绘制区域,来产生WM_PAINT消息.   例如,可以使用InvalidateRect声明一个需要重新绘制的区域.    2 WM_PAINT的注意点    2.1 如果一个消息队列中,有多个WM_PAINT消息,只有最后一个WM_PAINT消息会被处理.    2.2 WM_PAINT消息处理中,

走进windows编程的世界-----窗口的注册及创建

1   窗口注册和创建 1.1WIN32 窗口程序创建步骤 1.WinMain入口函数的定义 2.WindowProc函数的定义 3.注册窗口类 RegisterClass.RegisterClassEX 4.创建窗口 CreateWindow.CreateWindowEx HWND CreateWindow( LPCTSTRlpClassName,//指向已注册的窗口类的名称的指针 LPCTSTRlpWindowName,//指向窗口名称的指针 DWORDdwStyle,//窗口的风格 int

走进windows编程的世界-----windows进程

Windows进程  1 Windows进程    进程是一个容器,包含了一个应用程序实例的各种资源.Windows多任务的操作系统,因此可以同时执行多个进程.      2 Windows进程的一些特点    2.1 进程中包含了执行代码等资源.    2.2 进程都具有私有的地址空间.    2.3 每个进程都有一个ID,标识进程.    2.4 每个进程都有自己的安全属性    2.5 至少要包含一个可以执行的线程.    二 进程的环境 1 环境信息的获取    获取:    LPVOI

走进windows编程的世界-----字符编码

1   字符编码 1.1编码的历史 1.1.1ASCII码 0=127 7位表示 1.1.2ASCII扩展码 0-255 8为表示. 代码页:通过代码也来切换对应的字符(数字表示) 1.1.3双字节字符集DBCS 使用一个或两个字节表示字符. 1.1.4Unicode编码 全部使用2个字节表示字符 内存 硬盘等资源占用变大.对编码支持度大. 字符集 1.2C 语言和编码 1.2.1单字节的字符和字符串 Char  cText = 'A'; Char * pszText ="ABCD"

走进windows编程的世界-----绘图相关

Windows绘图 1 图形绘制      1.1 图形绘制的方式      获取到绘图句柄-设备描述表(DC),使用相应的绘图的API,在设备上绘制图形.          1.2 颜色      R\G\B三色, 每种颜色8位, 共24位颜色.      32位颜色: 颜色数量24位颜色, 多出来的8位表示灰度.      16位: 颜色数量2的16次方.            Win32下,颜色的定义 COLORREF(DWORD), RGB宏定义颜色       COLORREF nCo

走进windows编程的世界-----位图及映射模式

1   位图的使用 1.1位图介绍 位图-通过保存在图像上每个点的颜色,生成响应的位图文件. 光栅图:图像点阵的保存 矢量图:绘图命令的保存. 1.2位图的使用 1.             加载位图资源 LoadBitap(); 2.             创建防止位图的DC CreateCompatibleDC 3.             将位图放入创建的DC SlectObject 4.             绘制位图到当前DC中 BitBlt 5.             取出位图

走进windows编程的世界-----入门篇

1   Windows编程基础 1.1Win32应用程序基本类型 1)  控制台程序 不须要完好的windows窗体,能够使用DOS窗体方式显示 2)  Win32窗体程序 包括窗体的程序,能够通过窗体与程序进行交互 3)  Win32库程序 提供已有的代码,供其它程序使用 动态库(DLL):是在运行的时候能够载入的. 静态库(LIB):是在编译链接是使用的程序.成为当前程序的一部分. 1.2头文件和库 1.2.1头文件 主要的头文件windows.h包括了windows经常使用的定义等,其它,