您的位置:首页 > 其它

创建透明窗口及其应用--屏幕画笔

2011-11-02 17:09 387 查看
一、使窗口透明其实很简单。就是一个函数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);

}

希望对你有所帮助!阿弥陀佛!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: