一种在注入进程中使用WTL创建无焦点不在任务栏出现“吸附”窗口的方法和思路(五)

2014-11-24 11:21:31 · 作者: · 浏览: 4
ttachWindow);

BEGIN_MSG_MAP_EX(CWTLTitleWindow)
MESSAGE_HANDLER( WM_SHOWWINDOW, OnShow )
MESSAGE_HANDLER( WM_DESTROY, OnDestroy)
MESSAGE_HANDLER( WM_QUIT, OnQuit )
MESSAGE_HANDLER( WM_MOUSEACTIVATE, OnMouseActive )
MESSAGE_RANGE_HANDLER( WM_USER, WM_USER + WM_USER, OnDealUserMsg )
CHAIN_MSG_MAP(_baseDblBufImpl)
END_MSG_MAP()

LRESULT OnShow(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnQuit(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnMouseActive(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnDealUserMsg(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
void DoPaint(HDC dc);

VOID Start();
VOID DealMsg( UINT uMsg );

private:
ECalcResult CalcTitleWindowXY( int& x, int& y );
VOID ShowWindow();
private:
HWND m_hAttachHWnd;
HINSTANCE m_hInstance;
HBITMAP m_hBitmap;
RECT m_hAttachWindowRect;
};
首先说一下双缓冲。我继承于CDoubleBufferWindowImpl。在消息映射中,我们要让我们不处理的消息交给基类处理
[cpp]
typedef CWTLTitleWindow _thisClass;
typedef CDoubleBufferImpl<_thisClass> _baseDblBufImpl;
[cpp] view plaincopy
CHAIN_MSG_MAP(_baseDblBufImpl)
同时实现DoPaint函数。
[cpp]
void CWTLTitleWindow::DoPaint( HDC dc )
{
CRect rc;
GetClientRect(&rc);
CMemoryDC MemDc( dc, rc );

HBRUSH hBitmapBrush = CreatePatternBrush(m_hBitmap);
if ( NULL == hBitmapBrush ) {
return;
}

MemDc.FillRect( &rc, hBitmapBrush );
DeleteObject( hBitmapBrush );
}
m_bBitmap是我在资源文件中的一个bmp图片,我们在Start函数中将其载入。在类释放时,将其delete。
[cpp]
CWTLTitleWindow::~CWTLTitleWindow(void)
{
if ( NULL != m_hBitmap ) {
DeleteObject( m_hBitmap );
}
}

VOID CWTLTitleWindow::Start()
{
#pragma warning(push)
#pragma warning(disable:4312)
if ( NULL == m_hInstance ) {
m_hInstance = (HINSTANCE)GetWindowLong( GWL_HINSTANCE );
}
#pragma warning(pop)
if ( NULL == m_hBitmap ) {
m_hBitmap = LoadBitmap( m_hInstance, MAKEINTRESOURCE(IDB_BITMAP1));
}
}
以上基本上算是完成了双缓冲的操作了,但是为了尽量减少刷新的次数,我会多加个判断:改变的位置和大小是否和现在的位置和大小一致,如果一致则不做任何操作,否则刷新。
[cpp]
ECalcResult CWTLTitleWindow::CalcTitleWindowXY(int& x, int& y )
{
ECalcResult eResult = EError;

do {
RECT rcAttachWindow;
if ( FALSE == ::GetWindowRect( m_hAttachHWnd, &rcAttachWindow ) ) {
break;
}

if ( rcAttachWindow.left == m_hAttachWindowRect.left
&& rcAttachWindow.right == m_hAttachWindowRect.right
&& rcAttachWindow.top == m_hAttachWindowRect.top
&& rcAttachWindow.bottom == m_hAttachWindowRect.bottom )
{
eResult = ENoChange;
break;
}
else {
m_hAttachWindowRect = rcAttachWindow;
}

x = ( rcAttachWindow.left + rcAttachWindow.right - TIPWINDTH ) / 2;
y = rcAttachWindow.top;

eResult = ESuc;
} while (0);

return eResult;
}
再说下无焦点窗口的细节。
首先窗口样式要有WS_POPUP,网上有人说还要加上WS_VISIBLE,但是我觉得没必要。其次扩展属性要有WS_EX_NOACTIVATE。再次我们要处理WM_MOUSEACTIVATE消息。

[cpp]
MESSAGE_HANDLER( WM_MOUSEACTIVATE, OnMouseActive )
[cpp] view plaincopy
LRESULT CWTLTitleWindow::OnMouseActive( UINT uMsg, WPARAM wParam, LP