• Windows程序设计零基础自学_6_键盘_之键盘消息_实例代码


          好久没有学习Windows下的编程了, 因为我发现在学习Delphi时;看书的时候一会儿就涉及到windows编程的机制了。

    因此在今天有时间的时候学习一下windows的编程。

    View Code
    #include <windows.h>
    //#include "sysmets.h"

    LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);

    int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int iShowCmd)
    {
    static TCHAR szAppName[]=TEXT("SysMets4");
    static TCHAR szNeedNT[]=TEXT("You need winNT to run this program!");
    HWND hwnd;
    MSG msg;
    WNDCLASS wndclass;

    wndclass.cbClsExtra
    =0;
    wndclass.cbWndExtra
    =0;
    wndclass.hbrBackground
    =(HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.hCursor
    =LoadCursor(NULL,IDC_ARROW);
    wndclass.hIcon
    =LoadIcon(NULL,IDI_APPLICATION);
    wndclass.hInstance
    =hInstance;
    wndclass.lpfnWndProc
    =WndProc;
    wndclass.lpszClassName
    =szAppName;
    wndclass.lpszMenuName
    =NULL;
    wndclass.style
    =CS_VREDRAW | CS_HREDRAW;

    if(!RegisterClass(&wndclass))
    {
    MessageBox(NULL,szNeedNT,
    "Warning",MB_OK);
    return 0;
    }

    hwnd
    =CreateWindow(wndclass.lpszClassName,
    szAppName,
    WS_OVERLAPPEDWINDOW
    |WS_VSCROLL|WS_HSCROLL,
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    NULL,
    NULL,
    hInstance,
    NULL);

    ShowWindow(hwnd,iShowCmd);
    UpdateWindow(hwnd);

    while(GetMessage(&msg,NULL,0,0))
    {
    TranslateMessage(
    &msg);
    DispatchMessage(
    &msg);
    }
    return msg.wParam;
    }

    LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
    {
    HDC hdc;
    PAINTSTRUCT ps;
    static int cxChar,
    cxCaps,
    cyChar,
    cxClient,
    cyClient,
    iMaxWidth;
    int i,
    x,
    y,
    iVertPos,
    iHorzPos,
    iPaintBeg,
    iPaintEnd;

    SCROLLINFO si;
    //通过这个结构体来处理与滚动条相关的消息
    /*
    结构体的SCROLLINFO
    typedef struct tagSCROLLINFO
    {
    UINT cbSize; //这个字段表示的是结构体变量的大小, 通常设定为cbsize=sizeof SCROLLINFO;
    UINT fMask; //调用GetScrollInfo函数和SetScrollPosInfo函数时想要设定的值
    int nMin; //V_Range或者R_Range的最小值
    int nMax; //滚动范围的最大值
    UINT nPage; // 页面的大小, 这个值一般是cyClient/cyChar的大小
    int nPos; // 滚动条的当前位置
    int nTrackPos; //
    } SCROLLINFO, FAR *LPSCROLLINFO;
    fMask指定使用结构中哪些成员,不指定的就不使用;可以是以下几个值的任意组合
    SIF_ALL
    SIF_DISABLENOSCROLL
    SIF_PAGE
    SIF_POS
    SIF_RANGE
    SIF_TRACKPOS
    函数SetScrollInfo和GetScrollInfo的参数LPSCROLLINFO lpsi指向该结构。在程序中,可以定义如下的SCROLLINFO结构型态:
       SCROLLINFO si ;
      在调用SetScrollInfo或GetScrollInfo之前,必须将cbSize字段设定为结构的大小:
       si.cbSize = sizeof (si) ;
       或
       si.cbSize = sizeof (SCROLLINFO) ;
      
      把fMask字段设定为一个以上以SIF前缀开头的旗标,并且可以使用C的位操作OR运算子(|)组合这些旗标。
      SetScrollInfo函数使用SIF_RANGE旗标时,必须把nMin和nMax字段设定为所需的卷动列范围。
    GetScrollInfo函数使用SIF_RANGE旗标时,应把nMin和nMax字段设定为从函数传回的目前范围。
       SIF_POS旗标也一样。当通过SetScrollInfo使用它时,必须把结构的nPos字段设定为所需的位置。
    可以通过GetScrollInfo使用SIF_POS旗标来取得目前位置。
      使用SIF_PAGE旗标能够取得页面大小。用SetScrollInfo函数把nPage设定为所需的页面大小。
    GetScrollInfo使用SIF_PAGE旗标可以取得目前页面的大小。如果不想得到比例化的卷动列,就不要使用该旗标。
      当处理带有SB_THUMBTRACK或SB_THUMBPOSITION通知码的WM_VSCROLL或WM_HSCROLL消息时,通过GetScrollInfo只使用SIF_TRACKPOS旗标。
    从函数的传回中,SCROLLINFO结构的nTrackPos字段将指出目前的32位的卷动方块位置。

    */

    //TCHAR szBuffer[10];

    TEXTMETRIC tm;

    switch(message)
    {
    case WM_CREATE:
    hdc
    =GetDC(hwnd);
    /*
    tm结构体的定义:

    */
    GetTextMetrics(hdc,
    &tm); //通过这个函数获取设备内容中关于字符系统信息
    cxChar=tm.tmAveCharWidth; //表示字符的平均宽度
    cyChar=tm.tmHeight+tm.tmExternalLeading; //字符的高度

    cxCaps
    =(tm.tmPitchAndFamily & 1 ? 3:2)*cxChar /2;
    ReleaseDC(hwnd,hdc);

    iMaxWidth
    =40 * cxChar + 22 * cxCaps;
    return 0;
    case WM_SIZE:
    /*
    WM_SIZE消息:
    The WM_SIZE message is sent to a window after its size has changed.
    当窗口大小发生变化时发送给窗口的消息。
    当窗口处理函数接收到WM_SIZE消息时, message会接收一个wm_size消息,而消息的附加消息
    会保存在wParam中,其中wParam分为两段:
    低字: 保存窗口大小改变后x方向客户区的大小
    高字: 保存窗口大小改变后y方向客户区的大小
    */
    cxClient
    =LOWORD(lParam);
    cyClient
    =HIWORD(lParam);

    si.cbSize
    =sizeof si;
    //在函数中使用滚动条的滚动范围信息和页面大小信息,这个地方还需要进一步理解
    si.fMask=SIF_RANGE | SIF_PAGE;
    si.nMin
    = 0;
    si.nMax
    = 100-1;
    si.nPage
    = cyClient/cyChar;
    SetScrollInfo(hwnd,SB_VERT,
    &si,TRUE); //SB_VERT:用于窗口中标准垂直滚动条,此处函数仅改变垂直方向的信息

    si.cbSize
    =sizeof si;
    si.fMask
    =SIF_RANGE | SIF_PAGE;
    si.nMin
    = 0;
    si.nMax
    =2+iMaxWidth+cyChar;
    si.nPage
    =cxClient/cxChar;
    SetScrollInfo(hwnd,SB_HORZ,
    &si,TRUE); //SB_HORZ:用于窗口中水平滚动条,此处函数仅改变水平方向滚动条的信息
    return 0;
    case WM_VSCROLL:
    /*
    WM_VSCROLL:窗口的垂直滚动条消息。 当接收到这个消息时,wParam参数会附加消息码/通知码。

    wParam附加通知码存在该参数的低字, 可以通过LOWORD获取这个通知码消息,并且在一个switch中进行
    进行处理。
    */
    si.cbSize
    =sizeof(si);
    si.fMask
    =SIF_ALL;
    GetScrollInfo(hwnd,SB_VERT,
    &si);
    iVertPos
    =si.nPos;
    switch(LOWORD(wParam))
    {
    case SB_TOP:
    si.nPos
    =si.nMin;
    break;
    case SB_BOTTOM:
    si.nPos
    =si.nMax;
    break;
    case SB_LINEUP:
    si.nPos
    += -1;
    break;
    case SB_LINEDOWN:
    si.nPos
    += 1;
    break;
    case SB_PAGEUP:
    si.nPos
    -=si.nPage;
    break;
    case SB_PAGEDOWN:
    si.nPos
    =si.nPos+si.nPage;
    break;
    case SB_THUMBTRACK:
    si.nPos
    =si.nTrackPos;
    break;
    default:
    break;
    }
    //Scroll 附加消息处理

    si.fMask
    =SIF_POS;
    SetScrollInfo(hwnd,SB_VERT,
    &si,TRUE);
    GetScrollInfo(hwnd,SB_VERT,
    &si);

    if(si.nPos!=iVertPos)
    {
    ScrollWindow(hwnd,
    0,cyChar*(iVertPos-si.nPos),NULL,NULL);
    UpdateWindow(hwnd);
    }
    return 0;
    case WM_HSCROLL:
    /*
    WM_HSCROLL:窗口的水平滚动条消息。 当接收到这个消息时,wParam参数会附加消息码/通知码。

    wParam附加通知码存在该参数的低字, 可以通过LOWORD获取这个通知码消息,并且在一个switch中进行
    进行处理。
    */
    si.cbSize
    =sizeof(si);
    si.fMask
    =SIF_ALL;
    GetScrollInfo(hwnd,SB_HORZ,
    &si);
    iHorzPos
    =si.nPos;
    switch(LOWORD(wParam))
    {
    case SB_LINELEFT:
    si.nPos
    += -1;
    break;
    case SB_LINERIGHT:
    si.nPos
    ++;
    break;
    case SB_PAGELEFT:
    si.nPos
    -=si.nPage;
    break;
    case SB_PAGERIGHT:
    si.nPos
    +=si.nPos;
    break;
    case SB_THUMBPOSITION:
    si.nPos
    =si.nTrackPos;
    break;
    default:
    break;
    }
    // scroll 附加消息处理

    si.fMask
    =SIF_POS;
    SetScrollInfo(hwnd,SB_HORZ,
    &si,TRUE);
    GetScrollInfo(hwnd,SB_HORZ,
    &si);

    if(si.nPos != iHorzPos)
    {
    ScrollWindow(hwnd,cxChar
    *(iHorzPos-si.nPos),0,NULL,NULL);
    }
    return 0;
    case WM_KEYDOWN:
    /*
    WM_KEYDOWN: 窗口的键盘消息
    键盘消息分为:
    WM_KEYDOWN WM_KEYUP
    WM_SYSKEYDOWN WM_SYSKEYUP
    这里处理的是非系统键按下消息。
    因为键比较多,因此也需要一个消息的附加信息, 这个附加信息还是通过wParam参数进行传递

    通常键盘消息的wParam附加信息,成为虚拟键码。 这个参数信息通常用VK_ 开头表示。

    在键盘消息里面lParam参数也包含了丰富的信息,这些信息与lParam各个位的取值相关。
    */
    switch(wParam)
    {
    case VK_HOME:
    SendMessage(hwnd,WM_VSCROLL,SB_TOP,
    0);
    break;
    case VK_END:
    SendMessage(hwnd,WM_VSCROLL,SB_BOTTOM,
    0);
    break;
    case VK_PRIOR:
    SendMessage(hwnd,WM_VSCROLL,SB_PAGEUP,
    0);
    break;
    case VK_NEXT:
    SendMessage(hwnd,WM_VSCROLL,SB_PAGEDOWN,
    0);
    break;
    case VK_UP:
    SendMessage(hwnd,WM_VSCROLL,SB_LINEUP,
    0);
    break;
    case VK_DOWN:
    SendMessage(hwnd,WM_VSCROLL,SB_LINEDOWN,
    0);
    break;
    case VK_LEFT:
    SendMessage(hwnd,WM_HSCROLL,SB_LINELEFT,
    0);
    break;
    case VK_RIGHT:
    SendMessage(hwnd,WM_HSCROLL,SB_LINERIGHT,
    0);
    break;
    case VK_LWIN:
    MessageBox(hwnd,
    "You have press left win key!","提示",MB_OK);
    break;
    }
    //keydown 消息处理

    case WM_PAINT:
    hdc
    =BeginPaint(hwnd,&ps);
    si.cbSize
    =sizeof(si);
    si.fMask
    =SIF_POS;
    GetScrollInfo(hwnd,SB_VERT,
    &si);
    iVertPos
    =si.nPos;

    GetScrollInfo(hwnd,SB_HORZ,
    &si);
    iHorzPos
    =si.nPos;

    iPaintBeg
    =max(0,iVertPos+ps.rcPaint.top/cyChar);
    iPaintEnd
    =min(1000-1,iVertPos+ps.rcPaint.bottom/cyChar);

    for(i=iPaintBeg;i<=iPaintEnd;i++)
    {
    x
    =cxChar* (1-iHorzPos);
    y
    =cxChar*(1-iVertPos);

    TextOut(hdc,x,y,
    "abc",strlen("abc"));

    TextOut(hdc,x
    +22*cxCaps,y,"abcdefg",strlen("abcdefg"));

    SetTextAlign(hdc,TA_RIGHT
    | TA_TOP);

    }
    //for 循环
    EndPaint(hwnd,&ps);
    return 0;
    case WM_DESTROY:
    PostQuitMessage(
    0);
    return 0;
    }
    return DefWindowProc(hwnd,message,wParam,lParam);

    }

          我发现在目前我学习过的windows编程知识里面,滚动条的处理和字符系统处理比较困难。

          哈哈, 希望自己能够坚持下去, 在2009年的时候,就打算学习win的编程,结果没有坚持下去,

          当时学习的东西又基本忘记了,

           好在目前有博客园,在这里记录学习的点滴,促使我一直坚持学习............

  • 相关阅读:
    lerna管理前端packages的最佳实践
    理解Python闭包,这应该是最好的例子
    Maven 初学+http://mvnrepository.com/
    逆向工程,调试Hello World !程序(更新中)
    github设置仓库可见性 私人仓库设置他人协作/可见
    flink 1.9.0 编译:flink-fs-hadoop-shaded 找不到
    中通消息平台 Kafka 顺序消费线程模型的实践与优化
    以友盟+U-Push为例,深度解读消息推送的筛选架构解决方案应用与实践
    idea新建spring boot项目使用maven引入依赖失败,pom.xml文件中project标签报错
    RabbitMQ (十二) 消息确认机制
  • 原文地址:https://www.cnblogs.com/volcanol/p/2108972.html
Copyright © 2020-2023  润新知