最近学了些关于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=, int winRight=, int winTop=, int winBottom=);
~WinClassBase(); virtual int HandleMessage(UINT message,WPARAM wParam,LPARAM lParam) = ;
virtual LPCTSTR GetMyClassName() = ; //创建窗口
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+); }
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_

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=;
for(i=; i<registeredClassArray.size(); ++i)
{
if( registeredClassArray[i] == std::wstring(this->GetMyClassName()) )
{
break;
}
} //注册
if( i == registeredClassArray.size() )
{
WNDCLASS win; win.cbClsExtra = ;
win.cbWndExtra = ;
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( != ::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[] = {};
::swprintf(errorMsg, , 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();
break;
default:
if(pThis != NULL && pThis->HandleMessage(message, wParam, lParam) == )
{
return DefWindowProc(hwnd, message, wParam, lParam);
}
else if(pThis == NULL)
{
return DefWindowProc(hwnd, message, wParam, lParam);
} break;
} return ;
} 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 ;
}

KeyBoard.h

#pragma once

#include "WinClassBase.h"

#define MAX_LINE 1000

class KeyBoard : public WinClassBase
{
public:
KeyBoard(HINSTANCE hInastance, HWND HwndParent = NULL, int winLeft=, int winRight=, int winTop=, int winBottom=);
~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][];
};

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 - ;
m_scrollinfo.nMin = ;
m_scrollinfo.nPos = ;
m_line = ; return ;
}
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 ;
}
case WM_VSCROLL:
{
switch(LOWORD(wParam))
{
case SB_BOTTOM:
m_scrollinfo.nPos = m_line;
break;
case SB_LINEDOWN:
m_scrollinfo.nPos = (m_scrollinfo.nPos+);
break;
case SB_LINEUP:
if( m_scrollinfo.nPos >= )
m_scrollinfo.nPos = m_scrollinfo.nPos-;
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 ;
}
case WM_CHAR:
{
if(m_line < MAX_LINE)
{
wmemset(m_charArray[m_line], , );
swprintf(m_charArray[m_line], , 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, );
else
{
RECT rect;
rect.left = ;
rect.right = m_rect.right;
rect.top = ((m_line-) % m_scrollinfo.nPage) * m_textMetric.tmHeight;
rect.bottom = rect.top + m_textMetric.tmHeight;
InvalidateRect(m_hWnd, &rect, TRUE);
}
} return ;
}
case WM_PAINT:
{
PAINTSTRUCT paint;
HDC hdc = ::BeginPaint(m_hWnd, &paint);
for(int i=; i<(int)m_scrollinfo.nPage && i+m_scrollinfo.nPos<MAX_LINE; i++)
{
if( i+m_scrollinfo.nPos >= m_line )
::TextOut(hdc, , i*m_textMetric.tmHeight, TEXT(""), );
else
::TextOut(hdc, , 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 ;
}
} return ;
}
LPCTSTR KeyBoard::GetMyClassName()
{
return TEXT("keyBoardClass");
}

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();
}

win32键盘记录 -- 自定义窗口类的更多相关文章

  1. sizzle分析记录: 自定义伪类选择器

    可见性 :hidden :visible 隐藏对象没有宽高,前提是用display:none处理的 jQuery.expr.filters.hidden = function( elem ) { // ...

  2. WPF自定义窗口基类

    WPF自定义窗口基类时,窗口基类只定义.cs文件,xaml文件不定义.继承自定义窗口的类xaml文件的根节点就不再是<Window>,而是自定义窗口类名(若自定义窗口与继承者不在同一个命名 ...

  3. 探索Win32系统之窗口类(转载)

    Window Classes in Win32 摘要 本文主要介绍win32系统里窗口类的运做和使用机制,探索一些细节问题,使win32窗口类的信息更加明朗化. 在本文中,"类", ...

  4. WPF自学入门(九)WPF自定义窗口基类

    今天简单记录一个知识点:WPF自定义窗口基类,常用winform的人知道,winform的窗体继承是很好用的,写一个基础窗体,直接在后台代码改写继承窗体名.但如果是WPF要继承窗体,我个人感觉没有理解 ...

  5. Win32编程:窗口类样式+窗口外观样式+窗口显示样式

    1.窗口类样式WNDCLASS.style CS_VREDRAW 提供窗口位置变化事件和高度变化事件的处理程序,功能是重绘窗口 CS_HREDRAW 提供窗口位置变化事件和宽度变化事件的处理程序,功能 ...

  6. WPF 之 创建继承自Window 基类的自定义窗口基类

    开发项目时,按照美工的设计其外边框(包括最大化,最小化,关闭等按钮)自然不同于 Window 自身的,但窗口的外边框及窗口移动.最小化等标题栏操作基本都是一样的.所以通过查看资料,可按如下方法创建继承 ...

  7. WIN32窗口类风格和窗口风格(备查询)

    一.WNDCLASS typedef struct { UINT cbSize //这个结构体的长度,一般用sizeof(WNDCLASSEX)设置 UINT style //窗口式样 WNDPROC ...

  8. win32程序之子窗口编程

    win32程序之子窗口编程 一丶简介.什么是子窗口 在前边我们已经讲解了窗口的本质.以及如何注册窗口类跟创建窗口. 还讲了消息循环. 那么有很多窗口其实Windows已经帮我们创建出来了.我们直接使用 ...

  9. 【Q2D】如何导出自定义C++类给框架使用

    本文基于Quick cocos2d x这个游戏框架,为了行文流畅,后面都简称Q2D 导出自定义c++类给项目使用已经有了现成的例子了 详见:http://quick.cocos.org/?p=235 ...

随机推荐

  1. textarea中的文字自动换行问题

    在textarea中设置输入内容的自动换行,也是在CSS中设置word-wrap:break-word; 属性.需要额外注意的是textarea元素本身有一个warp属性,其取值含义如下: off:不 ...

  2. MongoDB实战指南(五):MongoDB中的聚集分析

    聚集操作是对数据进行分析的有效手段.MongoDB主要提供了三种对数据进行分析计算的方式:管道模式聚集分析,MapReduce聚集分析,简单函数和命令的聚集分析. 1. 管道模式进行聚集 这里所说的管 ...

  3. http://blog.csdn.net/carolzhang8406/article/details/7196011

    http://blog.csdn.net/carolzhang8406/article/details/7196011

  4. http://f.dataguru.cn/forum.php?mod=viewthread&tid=44212&fromuid=4771

    http://f.dataguru.cn/forum.php?mod=viewthread&tid=44212&fromuid=4771

  5. GridView使用CommandField删除列实现删除时提示确认框

    在.net2005提供的GridView中我们可以直接添加一个CommandField删除列完后在它的RowDeleting事件中完成删除 GridView在使用CommandField删除时弹出提示 ...

  6. Android fragment 回调函数改进

    由于fragment的onResume()等回调的调用时机与Activity不一样,导致用起来比较麻烦,所以我重新封装了一下回调函数,十分简单. 使用时只需要继承此基类,使用onFragmentXXX ...

  7. IIS UrlWriter配置(asp.net)

    前提在建虚拟目录或网站时注意以下设置第一步:下载URLRewriter 添加URLRewriter和ActionlessForm(不添加只能在VS实现,IIS下会找不到页面). 第二步:配置web.c ...

  8. bzoj1324

    经典例题 在<最小割模型在信息学竞赛中的应用>有详细的解答就不赘述了 主要想说,其实这题的几个结论其实是很好猜出来的: 当摸不清题目本质的时候,不妨多找几种情况,猜测一下 顺便推广一下几个 ...

  9. .NET(C#)调用webService获取客户端IP地址所属区域(非异步)

    功能描述: 此接口用于获取客户端访问的IP的地址所属的区域(国家,城市等).通过输入IP地址查询国家.城市.所有者等信息.没有注明国家的为中国输入参数:IP地址(自动替换 " ." ...

  10. Linux kernel ‘xfs_attrlist_by_handle()’函数缓冲区溢出漏洞

    漏洞名称: Linux kernel ‘xfs_attrlist_by_handle()’函数缓冲区溢出漏洞 CNNVD编号: CNNVD-201311-392 发布时间: 2013-11-29 更新 ...