zoukankan      html  css  js  c++  java
  • win32键盘记录 -- 自定义窗口类

    最近学了些关于window api编程的知识,于是琢磨编写一些键盘记录器,能够把输入的按键输出到窗口内,并且实现窗口自动滚动。

    封装窗口类使用了GWL_USERDATA字段来保存this指针,比较容易理解,缺点如果程序别的地方使用这个字段会引起崩溃...

    WinClassBase.h

    #ifndef _WINDOW_CLASS_BASE_
    #define _WINDOW_CLASS_BASE_
    
    #include <windows.h>
    #include <vector>
    #include <string>
    
    class WinClassBase
    {
    public:
        WinClassBase(HINSTANCE hInastance, HWND HwndParent = NULL, int winLeft=0, int winRight=600, int winTop=0, int winBottom=800);
        ~WinClassBase();
    
        virtual int HandleMessage(UINT message,WPARAM wParam,LPARAM lParam) = 0;
        virtual LPCTSTR GetMyClassName() = 0;
    
        //创建窗口
        void Create();
        //获取窗口句柄
        HWND GetMyHandle() const { return m_hWnd; }
    
        void ShowWindow(int nShowCmd);
        int  exec();
    
    protected:
        virtual UINT    GetMyClassStyle()        { return CS_VREDRAW | CS_HREDRAW; }
        virtual HICON    GetMyClassIcon()        { return NULL; }
        virtual HCURSOR GetMyClassCursor()        { return NULL; }
        virtual HBRUSH    GetMyClassBackground()    { return HBRUSH(COLOR_WINDOW+1); }
        virtual LPCTSTR GetMyClassMenuName()    { return NULL; }
    
        virtual LPCTSTR GetMyWindowName()        { return TEXT("wuyou"); }
        virtual DWORD    GetMyWindowStyle()        { return  WS_OVERLAPPEDWINDOW; }
        virtual HMENU    GetMyWindowMenu()        { return NULL; }
    private:
        //原始窗口
        static LRESULT CALLBACK WindowProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam);
        
    protected:
        HWND m_hWnd;
        HWND m_hWndParent;
        RECT m_rect;
        HINSTANCE m_hInastance;
    
        //已注册过的类的集合
        static std::vector<std::wstring> registeredClassArray;
    };
    
    #endif //_WINDOW_CLASS_BASE_
    View Code

    WinClassBase.cpp

    #include "WinClassBase.h"
    
    
    std::vector<std::wstring> WinClassBase::registeredClassArray;  
    
    WinClassBase::WinClassBase(HINSTANCE hInastance, HWND hWndParent, int winLeft, int winRight, int winTop, int winBottom)
    {
        m_hInastance = hInastance;
        
        m_hWndParent = hWndParent;
    
        m_rect.left = winLeft;
        m_rect.right = winRight;
        m_rect.top = winTop;
        m_rect.bottom = winBottom;
    
        m_hWnd = NULL;
    }
    
    WinClassBase::~WinClassBase(void)
    {
        if( this->m_hWnd != NULL && ::IsWindow(this->m_hWnd) )
        {
            ::DestroyWindow(this->m_hWnd);
        }
    }
    
    //创建窗口
    void WinClassBase::Create()
    {
        unsigned int i=0;
        for(i=0; i<registeredClassArray.size(); ++i)
        {
            if( registeredClassArray[i] == std::wstring(this->GetMyClassName()) )
            {
                break;
            }
        }
    
        //注册
        if( i == registeredClassArray.size() )
        {
            WNDCLASS win;
    
            win.cbClsExtra = 0;
            win.cbWndExtra = 0;
            win.hbrBackground = this->GetMyClassBackground();
            win.hCursor = this->GetMyClassCursor();
            win.hIcon = this->GetMyClassIcon();
            win.hInstance = m_hInastance;
            win.lpfnWndProc = WinClassBase::WindowProc;
            win.lpszClassName = this->GetMyClassName();
            win.lpszMenuName = this->GetMyClassMenuName();
            win.style = this->GetMyClassStyle();
            
            if(0 != ::RegisterClass(&win))
            {
                registeredClassArray.push_back(this->GetMyClassName());
            }
        }
    
        //创建窗口
        if( NULL == this->m_hWnd )
        {
            HWND hWnd = ::CreateWindow(this->GetMyClassName(),
                this->GetMyWindowName(),
                this->GetMyWindowStyle(),
                this->m_rect.left,
                this->m_rect.top,
                this->m_rect.right - this->m_rect.left,
                this->m_rect.bottom - this->m_rect.top,
                this->m_hWndParent,
                this->GetMyWindowMenu(),
                this->m_hInastance,
                (LPVOID)this
                );
    
            if(NULL == hWnd)
            {
                this->m_hWnd = NULL;
                WCHAR errorMsg[128] = {0};
                ::swprintf(errorMsg, 128, TEXT("CreateWindow Failed: %ld"), ::GetLastError());
                ::MessageBox(NULL, errorMsg, TEXT("Error"), MB_OK);
                return ;
            }
        }
    }
    
    LRESULT CALLBACK WinClassBase::WindowProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
    {
        WinClassBase *pThis = NULL;
    
        if(message == WM_CREATE)
        {
            pThis = (WinClassBase *)(((LPCREATESTRUCT)lParam)->lpCreateParams);
            pThis->m_hWnd = hwnd;
            ::SetWindowLong(hwnd, GWL_USERDATA, (LONG)pThis);
        }
        
        pThis = (WinClassBase *)::GetWindowLong(hwnd, GWL_USERDATA);
    
        switch(message)
        {
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            if(pThis != NULL && pThis->HandleMessage(message, wParam, lParam) == 0)
            {
                return DefWindowProc(hwnd, message, wParam, lParam);
            }
            else if(pThis == NULL)
            {
                return DefWindowProc(hwnd, message, wParam, lParam);
            }
    
            break;
        }
    
        return 0;
    }
    
    void WinClassBase::ShowWindow(int nShowCmd)
    {
        ::ShowWindow(this->m_hWnd, nShowCmd);
        ::UpdateWindow(this->m_hWnd);
    }
    int WinClassBase::exec()
    {
        MSG msg;
    
        while(::GetMessage(&msg, NULL, NULL, NULL))
        {
            ::TranslateMessage(&msg);
            ::DispatchMessage(&msg);
        }
    
        return 0;
    }
    View Code

    KeyBoard.h

    #pragma once
    
    #include "WinClassBase.h"
    
    #define MAX_LINE 1000
    
    class KeyBoard : public WinClassBase
    {
    public:
        KeyBoard(HINSTANCE hInastance, HWND HwndParent = NULL, int winLeft=0, int winRight=600, int winTop=0, int winBottom=800);
        ~KeyBoard(void);
    
    
        virtual int HandleMessage(UINT message,WPARAM wParam,LPARAM lParam);
        virtual LPCTSTR GetMyClassName();
    
        virtual DWORD    GetMyWindowStyle()        { return  WS_OVERLAPPEDWINDOW | WS_VSCROLL; }
        virtual LPCTSTR GetMyWindowName()        { return TEXT("键盘记录"); }
    
    private:
        int m_line;
        TEXTMETRIC m_textMetric;
        SCROLLINFO m_scrollinfo;
        
        TCHAR m_charArray[MAX_LINE][100];
    };
    View Code

    KeyBoard.cpp

    #include "KeyBoard.h"
    #include <wchar.h>
    
    KeyBoard::KeyBoard(HINSTANCE hInastance, HWND hWndParent, int winLeft, int winRight, int winTop, int winBottom)
        :WinClassBase(hInastance, hWndParent, winLeft, winRight, winTop, winBottom)
    {
    }
    
    KeyBoard::~KeyBoard(void)
    {
    }
    
    int KeyBoard::HandleMessage(UINT message,WPARAM wParam,LPARAM lParam)
    {
        switch(message)
        {
        case WM_CREATE:
        {
            HDC hdc = GetDC(m_hWnd);
            ::GetTextMetrics(hdc, &m_textMetric);
            ReleaseDC(m_hWnd, hdc);
            m_scrollinfo.cbSize = sizeof(m_scrollinfo);
            m_scrollinfo.nMax = MAX_LINE - 1;
            m_scrollinfo.nMin = 0;
            m_scrollinfo.nPos = 0;
            m_line = 0;
    
            return 1;
        }
        case WM_SIZE:
        {
            WORD newHeight = HIWORD(lParam);
            m_scrollinfo.nPage = newHeight / m_textMetric.tmHeight;
            m_scrollinfo.fMask = SIF_ALL;
            ::SetScrollInfo(m_hWnd, SB_VERT, &m_scrollinfo, TRUE);
    
            return 1;
        }
        case WM_VSCROLL:
        {
            switch(LOWORD(wParam))
            {
            case SB_BOTTOM:
                m_scrollinfo.nPos = m_line;
                break;
            case SB_LINEDOWN:
                m_scrollinfo.nPos = (m_scrollinfo.nPos+1);
                break;
            case SB_LINEUP:
                if( m_scrollinfo.nPos >= 0 )
                    m_scrollinfo.nPos = m_scrollinfo.nPos-1;
                break;
            case SB_PAGEDOWN:
                m_scrollinfo.nPos += m_scrollinfo.nPage;
                break;
            case SB_PAGEUP:
                m_scrollinfo.nPos -= m_scrollinfo.nPage;
                break;
            case SB_THUMBPOSITION:
                m_scrollinfo.nPos = HIWORD(wParam);
                break;
            case SB_THUMBTRACK:
                m_scrollinfo.nPos = HIWORD(wParam);
                break;
            }
    
            m_scrollinfo.fMask = SIF_POS;
            SetScrollInfo(m_hWnd, SB_VERT, &m_scrollinfo, TRUE);
            InvalidateRect(m_hWnd, NULL, TRUE);
    
            return 1;
        }
        case WM_CHAR:
        {
            if(m_line < MAX_LINE)
            {
                wmemset(m_charArray[m_line], 0, 100);
                swprintf(m_charArray[m_line], 100, TEXT("wParam = 0x%X    lParam = 0x%X  val = %c"), wParam, lParam, wParam);
                m_line ++;
                
                if(m_line >= (int)(m_scrollinfo.nPos + m_scrollinfo.nPage))
                    ::PostMessage(m_hWnd, WM_VSCROLL, SB_PAGEDOWN, 0);
                else
                {
                    RECT rect;
                    rect.left = 0;
                    rect.right = m_rect.right;
                    rect.top = ((m_line-1) % m_scrollinfo.nPage) * m_textMetric.tmHeight;
                    rect.bottom = rect.top + m_textMetric.tmHeight;
                    InvalidateRect(m_hWnd, &rect, TRUE);
                }
            }
    
            return 1;
        }
        case WM_PAINT:
        {
            PAINTSTRUCT paint;
            HDC hdc = ::BeginPaint(m_hWnd, &paint);
            for(int i=0; i<(int)m_scrollinfo.nPage && i+m_scrollinfo.nPos<MAX_LINE; i++)
            {
                if( i+m_scrollinfo.nPos >= m_line )
                    ::TextOut(hdc, 0, i*m_textMetric.tmHeight, TEXT(""), 0);
                else
                    ::TextOut(hdc, 0, i*m_textMetric.tmHeight, m_charArray[i+m_scrollinfo.nPos], wcslen(m_charArray[i+m_scrollinfo.nPos]));
            }
            ::EndPaint(m_hWnd, &paint);
            ::ReleaseDC(m_hWnd, hdc);
            return 1;
        }
        }
    
        return 0;
    }
    LPCTSTR KeyBoard::GetMyClassName()
    {
        return TEXT("keyBoardClass");
    }
    View Code

    main

    #include "KeyBoard.h"
    
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,int nShowCmd )
    {
        KeyBoard key(hInstance);
    
        key.Create();
        key.ShowWindow(nShowCmd);
    
        return key.exec();
    }
    View Code
  • 相关阅读:
    RGB空间与HSV空间的相互转换(C++实现,修正网上大多数的代码错误)
    SLIC superpixel实现分析
    开发自己PHP MVC框架(一)
    C++ 直方图匹配算法代码
    准确率与召回率
    Github干货系列:C++资源集合-
    ezw证件照芯片压缩算法
    格拉姆-施密特正交化
    [轉]sendpage漏洞分析 CVE-2009-2692
    ptrace
  • 原文地址:https://www.cnblogs.com/liuxin13/p/5997370.html
Copyright © 2011-2022 走看看