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

 

posted @ 2016-10-25 17:04  无忧望月  阅读(480)  评论(1编辑  收藏  举报
levels of contents