创建透明窗口及其应用--屏幕画笔
示例代码下载:创建透明窗口(屏幕画笔).zip (请不要直接使用迅雷下载)
注:VC6下编译通过
一、使窗口透明其实很简单。就是一个函数SetLayeredWindowAttributes
步骤如下:
步骤一:让窗口具透明的特性
::SetWindowLong(m_hWnd,GWL_EXSTYLE, GetWindowLong(m_hWnd,GWL_EXSTYLE)|WS_EX_LAYERED);
当你不希望窗口透明时,就使这个添加的属性去掉就可以了,如下:
//取消透明
::SetWindowLong(m_hWnd,GWL_EXSTYLE, GetWindowLong(m_hWnd,GWL_EXSTYLE)& ~WS_EX_LAYERED);
当然,最后别忘记先定义WS_EX_LAYERED,否则编译时会无法识别WS_EX_LAYERED
#define WS_EX_LAYERED 0x00080000
步骤二:获得SetLayeredWindowAttributes函数
这个函数需要从USER32.DLL里获得,调用如下。
//获取模块里的函数
HINSTANCE hInst=GetModuleHandle(_T("USER32.DLL"));
BOOL (WINAPI *SetLayeredWindowAttributes)(HWND,COLORREF,BYTE,DWORD)=
(BOOL (WINAPI*) (HWND,COLORREF,BYTE,DWORD))GetProcAddress(hInst,"SetLayeredWindowAttributes");
这样我们就获得了函数SetLayeredWindowAttributes。函数解释如下:
BOOL SetLayeredWindowAttributes(
HWND hwnd, handle to the layered window
COLORREF crKey, specifies the color key
BYTE bAlpha, value for the blend function
DWORD dwFlags action);
其中dwFlags有LWA_ALPHA(值为2)和LWA_COLORKEY(值为1)两种设置,如果LWA_ALPHA被设置的话,
通过bAlpha参数指定窗体的透明度;如果LWA_COLORKEY标志被设置的话,则指定关键色为crKey,
该颜色所覆盖的区域将从窗体去除,去除后的区域将不再进行点击检测,其他颜色则正常显示。
如果阿尔法混合值设置为0,其窗口区域同样不进行点击检测。
步骤三:调用函数设置透明。
方式一:设置我们指定的颜色透明掉。(第4参数设为1,此时第二个参数是要透明的颜色,其他参数不管)
//设置窗口透明。第4参数为1时,第二个参数是要透明的颜色
SetLayeredWindowAttributes(m_hWnd,RGB(244,243,238),0,1);
具体代码如下:(复制粘贴后可以直接使用)
HINSTANCE hInst=GetModuleHandle(_T("USER32.DLL"));
if (hInst)
{
//获取模块里的函数
BOOL (WINAPI *SetLayeredWindowAttributes)(HWND,COLORREF,BYTE,DWORD)=
(BOOL (WINAPI*) (HWND,COLORREF,BYTE,DWORD))GetProcAddress(hInst,"SetLayeredWindowAttributes");
//函数指针正确获取
if(SetLayeredWindowAttributes)
{
//让窗口具透明的特性
::SetWindowLong(m_hWnd,GWL_EXSTYLE, GetWindowLong(m_hWnd,GWL_EXSTYLE)|WS_EX_LAYERED);
//设置窗口透明。第4参数为1时,第二个参数是要透明的颜色
SetLayeredWindowAttributes(m_hWnd,RGB(244,243,238),0,1);
}
FreeLibrary(hInst); //释放调模块句柄
}
方式二:设置窗口具有某种透明度。(第4参数设为2,此时第三个参数表示透明度的值,其他参数不管)
//设置窗口透明。第4参数为2时,第三个参数表示透明度
SetLayeredWindowAttributes(m_hWnd, 0, 80, 2);
具体代码如下:(复制粘贴后可以直接使用)
HINSTANCE hInst=GetModuleHandle(_T("USER32.DLL"));
if (hInst)
{
//获取模块里的函数
BOOL (WINAPI *SetLayeredWindowAttributes)(HWND,COLORREF,BYTE,DWORD)=
(BOOL (WINAPI*) (HWND,COLORREF,BYTE,DWORD))GetProcAddress(hInst,"SetLayeredWindowAttributes");
//函数指针正确获取
if(SetLayeredWindowAttributes)
{
//让窗口具透明的特性
::SetWindowLong(m_hWnd,GWL_EXSTYLE, GetWindowLong(m_hWnd,GWL_EXSTYLE)|WS_EX_LAYERED);
//设置窗口透明。第4参数为2时,第三个参数表示透明度
SetLayeredWindowAttributes(m_hWnd, 0, 80, 2);
}
FreeLibrary(hInst); //释放调模块句柄
}
二、透明窗口的应用:屏幕画笔
1.我们可以创建一个透明的窗口。让其背景色透明掉。比如背景色是RGB(244,243,238),我们使用:
SetLayeredWindowAttributes(m_hWnd,RGB(244,243,238),0,1);
就可以把背景色去掉。
2.当我们使用窗口的屏幕DC画图时,由于颜色不是背景颜色RGB(244,243,238),所以我们画的线都会保留在透明窗口上。
3.把窗口的边框去掉,并且覆盖整个屏幕。而且要置窗口为最顶层窗口。这样就可以实现屏幕画笔了。
4.画图时,由于窗口透明了,所以我们的鼠标消息不会给透明窗口捕获到。这时我们可以安装一个低级鼠标钩子(之所以要用
低级鼠标钩子因为它够方便,直接写在程序里,不用dll),用于捕获鼠标的说有消息。
具体代码如下:当然你也可以参考我上面提供的源代码。
HWND g_hWnd;
POINT LastPoint;
bool IsDrawingLine=false;
BOOL CDemoDlg::OnInitDialog()
{
CDialog::OnInitDialog();
SetIcon(AfxGetApp()->LoadIcon(IDR_MAINFRAME), TRUE); // Set big icon
::SetWindowPos(m_hWnd,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE); //设置窗口最顶
static CLoadMyLibrary inst(m_hWnd);
//-----------------------------------------------------------------------------
g_hWnd=m_hWnd;
OnButton1();
return TRUE;
}
/****************************************************************************
低级鼠标钩子
#define _WIN32_WINNT 0x0500 //必须在stdafx.h中添加这一句
****************************************************************************/
HHOOK g_LowLevelMouseHook=NULL; //钩子句柄
LRESULT CALLBACK LowLevelMouseProc(int nCode,WPARAM wParam, LPARAM lParam)
{
if (nCode<0 )
return CallNextHookEx(g_LowLevelMouseHook,nCode,wParam,lParam);
static POINT point;
point=(POINT)((MSLLHOOKSTRUCT *)lParam)->pt;
switch (wParam)
{
case WM_LBUTTONDOWN:
{
TCHAR ClassName[20]={0};
::GetClassName(::WindowFromPoint(point),ClassName,sizeof(ClassName)/sizeof(TCHAR));
if (_tcscmp(ClassName,_T("Button"))==0)
break;
::ScreenToClient(g_hWnd,&point);
LastPoint=point;
IsDrawingLine=true;
return 1;
}
break;
case WM_LBUTTONUP:
{
IsDrawingLine=false;
}
break;
case WM_MOUSEMOVE:
{
if (IsDrawingLine)
{
::ScreenToClient(g_hWnd,&point);
//画鼠标移动痕迹
HDC hdc=::GetDC(g_hWnd); //画曲线
HPEN pen=::CreatePen(PS_SOLID,4,RGB(30,30,30));
SelectObject (hdc,pen) ;
::MoveToEx(hdc,LastPoint.x,LastPoint.y,NULL);
::LineTo(hdc,point.x,point.y);
LastPoint=point;
DeleteObject(pen);
::ReleaseDC(NULL,hdc) ;
}
}
break;
}
return CallNextHookEx(g_LowLevelMouseHook,nCode,wParam,lParam); //传递钩子信息
}
#define WS_EX_LAYERED 0x00080000
void CDemoDlg::OnButton1()
{
HINSTANCE hInst=GetModuleHandle(_T("USER32.DLL"));
if (hInst)
{
//获取模块里的函数
BOOL (WINAPI *SetLayeredWindowAttributes)(HWND,COLORREF,BYTE,DWORD)=
(BOOL (WINAPI*) (HWND,COLORREF,BYTE,DWORD))GetProcAddress(hInst,"SetLayeredWindowAttributes");
//函数指针正确获取
if(SetLayeredWindowAttributes)
{
//让窗口具透明的特性
::SetWindowLong(m_hWnd,GWL_EXSTYLE, GetWindowLong(m_hWnd,GWL_EXSTYLE)|WS_EX_LAYERED);
//设置窗口透明。第4参数为1时,第二个参数是要透明的颜色
SetLayeredWindowAttributes(m_hWnd,RGB(244,243,238),0,1);
}
FreeLibrary(hInst); //释放调模块句柄
}
}
void CDemoDlg::OnButton5()
{
HINSTANCE hInst=GetModuleHandle(_T("USER32.DLL"));
if (hInst)
{
//获取模块里的函数
BOOL (WINAPI *SetLayeredWindowAttributes)(HWND,COLORREF,BYTE,DWORD)=
(BOOL (WINAPI*) (HWND,COLORREF,BYTE,DWORD))GetProcAddress(hInst,"SetLayeredWindowAttributes");
//函数指针正确获取
if(SetLayeredWindowAttributes)
{
//让窗口具透明的特性
::SetWindowLong(m_hWnd,GWL_EXSTYLE, GetWindowLong(m_hWnd,GWL_EXSTYLE)|WS_EX_LAYERED);
//设置窗口透明。第4参数为2时,第三个参数表示透明度
SetLayeredWindowAttributes(m_hWnd, 0, 80, 2);
}
FreeLibrary(hInst); //释放调模块句柄
}
}
void CDemoDlg::OnButton2()
{
//取消透明
::SetWindowLong(m_hWnd,GWL_EXSTYLE, GetWindowLong(m_hWnd,GWL_EXSTYLE)& ~WS_EX_LAYERED);
}
void CDemoDlg::OnButton3()
{
//取消所有边框
::SetWindowLong(m_hWnd,GWL_STYLE,GetWindowLong(m_hWnd,GWL_STYLE)
& ~WS_CAPTION & ~WS_THICKFRAME );
::SetWindowPos(m_hWnd,NULL,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_FRAMECHANGED);
// //如果有WS_EX_DLGMODALFRAME还要取消WS_EX_DLGMODALFRAME
// ::SetWindowLong(m_hWnd,GWL_EXSTYLE,GetWindowLong(m_hWnd,GWL_EXSTYLE)
// & ~WS_EX_DLGMODALFRAME);
// ::SetWindowPos(m_hWnd,NULL,0,0,0,0,SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOSIZE);
int cx=GetSystemMetrics(SM_CXSCREEN);
int cy=GetSystemMetrics(SM_CYSCREEN);
::SetWindowPos(m_hWnd,HWND_TOPMOST,0,0,cx,cy,NULL);
}
void CDemoDlg::OnButton4()
{
//添加标题栏
::SetWindowLong(m_hWnd,GWL_STYLE,GetWindowLong(m_hWnd,GWL_STYLE)
| WS_CAPTION );
::SetWindowPos(m_hWnd,HWND_TOPMOST,100,100,400,400,SWP_FRAMECHANGED);
}
void CDemoDlg::OnButton6()
{
if(g_LowLevelMouseHook!=NULL)
return;
//start Low Level mouse hook
g_LowLevelMouseHook=SetWindowsHookEx(WH_MOUSE_LL,LowLevelMouseProc,GetModuleHandle(NULL),0);
if(!g_LowLevelMouseHook)
::MessageBox(m_hWnd,TEXT("SetWindowsHookEx LowLevelMouseProc failed"),NULL,MB_OK);
}
void CDemoDlg::OnButton8()
{
//stop Low Level mouse hook
UnhookWindowsHookEx(g_LowLevelMouseHook);
g_LowLevelMouseHook=NULL;
}
void CDemoDlg::OnButton7()
{
::InvalidateRect(m_hWnd,NULL,true);
}
希望对你有所帮助!阿弥陀佛!