分享
 
 
 

Windows 层窗口的使用

王朝vc·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

Windows从windows2000开始,提供了一种叫做Layered的窗口风格,通过使用这种窗口风格,我们就可以创建透明的窗口或者半透明的窗口,在这里我将使用一个比较简单的例子来说明如何使用这种新的窗口风格。

首先我们说明一下windows API对层窗口的支持情况。在创建窗口的时候可以直接使用CreateWindowEx来创建层窗口,或者在创建了普通的窗口之后使用SetWindowLong()来修改已有的窗口的风格. Windows层窗口的窗口风格是WS_EX_LAYERED,创建了层窗口的同时,你也就创建了透明窗口, 因为层窗口会同时设置透明窗口的风格。

在我们创建了层窗口之后,我们可以调用API SetLayeredWindowAttributes()来设置层窗口的属性,这个API函数的原型是这样的

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

);

这个函数的主要功能就是设置层窗口的缺省的属性,第一个参数hwnd就是我们要设置的层窗口的句柄,第二个参数crKey是我们要指定的一个色彩的关键值,这个值在第4个参数设置为LWA_COLORKEY的时候有效,这个参数的主要目的是过滤掉这里指定的颜色,比如我们在这里把这个颜色设置成白色,那么当我们向窗口上画白色的时候, 所有的白色都会被滤掉,这样画白色的地方就变得透明了。第3个参数bAlpha是我们指定的用来设置blend功能的,这个参数在第4个参数设置成LWA_ALPHA的时候有效。如果设置了这个参数, 我们就可以创造一种半透明的窗口效果。

在使用COLORKEY方式的时候,我们可以得到一种透明的窗口,而且在这种情况下,所有透明的地方,都不会接受鼠标消息,鼠标消息都会被直接发送到层窗口下面的窗口上。

关于层窗口另一个比较重要的API是UpdateLayeredWindow(),这个函数的原型如下:

BOOL UpdateLayeredWindow(

HWND hwnd, // handle to layered window

HDC hdcDst, // handle to screen DC

POINT *pptDst, // new screen position

SIZE *psize, // new size of the layered window

HDC hdcSrc, // handle to surface DC

POINT *pptSrc, // layer position

COLORREF crKey, // color key

BLENDFUNCTION *pblend, // blend function

DWORD dwFlags // options

);

这个函数看起来好像参数很多,其实和BitBlt函数差不多,不过它是用在层窗口上,其中的crKey和SetLayeredWindowAttributes中的crKey是一样的,pblend是一个结构,其中的内容也是很简单,这里不作介绍了

COLORKEY和ALPHA方式同时只能有一个有效,所以dwFlags就是用来决定这个的,和SetLayeredWindowAttributes不一样的是这个参数有三个选项可以使用ULW_ALPHA,ULW_COLORKEY,ULW_OPAQUE,前两个的作用和SetLayeredWindowAttributes一样,第三个就是指定这个窗口不透明。

SetLayeredWindowAttributes和UpdateLayeredWindow的另一个不同是SetLayeredWindowAttributes是在窗口创建之后调用一次就可以了,而UpdateLayeredWindow是用来处理windows的PAINT事件的。

在本文这个例子里我创建了一个时钟程序,这个程序除了表盘上的刻度和3个指针之外其他的地方都是透明的,而且一般情况下不会影响到你正常的应用操作。这个例子使用了ATL, 另外需要支持windows2000的sdk才能编译过去。

#define WINVER 0x0500

#define _WIN32_WINNT 0x0500

#define _WIN32_IE 0x0501

#define _RICHEDIT_VER 0x0200

#include <atlbase.h>

extern CComModule _Module;

#include <atlwin.h>

#include "stdatl.h"

#include <stdio.h>

#include <math.h>

#include <time.h>

#define PI 3.1415926

#define ID_CLOCKTIMER 101

CComModule _Module;

class CClockWindow : public CWindowImpl<CClockWindow, CWindow,

CWinTraits<WS_POPUP, WS_EX_LAYERED|WS_EX_TOOLWINDOW> >

{

BEGIN_MSG_MAP( CClockWindow )

MESSAGE_HANDLER(WM_TIMER, OnTimer)

MESSAGE_HANDLER(WM_CREATE, OnCreate)

MESSAGE_HANDLER( WM_PAINT, OnPaint )

MESSAGE_HANDLER( WM_DESTROY, OnDestroy )

MESSAGE_HANDLER(WM_NCHITTEST, OnNcHitTest)

END_MSG_MAP()

LRESULT OnNcHitTest(UINT, WPARAM, LPARAM, BOOL&)

{

return HTCAPTION;

}

LRESULT OnPaint( UINT, WPARAM, LPARAM, BOOL& )

{

PAINTSTRUCT ps;

HDC hDC = BeginPaint( &ps );

RECT rc;

GetWindowRect(&rc);

SetMapMode(hDC, MM_ISOTROPIC);

SetWindowExtEx(hDC, 1000, 1000, NULL);

SetViewportOrgEx(hDC, (rc.right - rc.left) / 2, (rc.bottom - rc.top) / 2, NULL);

SetViewportExtEx(hDC, rc.right - rc.left, - (rc.bottom - rc.top), NULL);

DrawClock(hDC);

EndPaint( &ps );

return 0;

}

LRESULT OnDestroy( UINT, WPARAM, LPARAM, BOOL& )

{

PostQuitMessage( 0 );

return 0;

}

LRESULT OnCreate(UINT, WPARAM, LPARAM, BOOL&)

{

SetTimer(ID_CLOCKTIMER, 500);

return 0;

}

LRESULT OnTimer(UINT, WPARAM, LPARAM, BOOL&)

{

HDC hDC = this->GetDC();

RECT rc;

GetWindowRect(&rc);

SetMapMode(hDC, MM_ISOTROPIC);

SetWindowExtEx(hDC, 1000, 1000, NULL);

SetViewportOrgEx(hDC, (rc.right - rc.left) / 2, (rc.bottom - rc.top) / 2, NULL);

SetViewportExtEx(hDC, rc.right - rc.left, - (rc.bottom - rc.top), NULL);

DrawClock(hDC);

ReleaseDC(hDC);

return 0;

}

void DrawClockSurface(HDC hDC)

{

HBRUSH hBkBrush = ::CreateSolidBrush(RGB(255, 255, 255));

HBRUSH hOldBrush = (HBRUSH)::SelectObject(hDC, hBkBrush);

::SetBkMode(hDC, TRANSPARENT);

::Ellipse(hDC, -510, -510, 510, 510);

int nRadius = 500 - 50;

int x, y;

HBRUSH hPointBrush = ::CreateSolidBrush(RGB(0, 0, 0));

::SelectObject(hDC, hPointBrush);

::DeleteObject(hBkBrush);

for (int i = 0; i < 60; i ++)

{

x = (int)(nRadius * sin((2 * i * PI) / 60));

y = (int)(nRadius * cos((2 * i * PI) / 60));

::Ellipse(hDC, x - 10, y - 10, x + 10, y + 10);

}

for (int i = 0; i < 12; i ++)

{

x = (int)(nRadius * sin((2 * i * PI) / 12));

y = (int)(nRadius * cos((2 * i * PI) / 12));

::Ellipse(hDC, x - 20, y - 20, x + 20, y + 20);

}

int nHour, nMin, nSec;

GetCurTime(nHour, nMin, nSec);

char sTime[20];

ZeroMemory(sTime, sizeof(sTime));

sprintf(sTime, "%02d:%02d:%02d", nHour, nMin, nSec);

SIZE sz;

::GetTextExtentPoint(hDC, sTime, (int)strlen(sTime), &sz);

::TextOut(hDC, -sz.cx / 2 - 1, -300, sTime, (int)strlen(sTime));

::SelectObject(hDC, hOldBrush);

::DeleteObject(hPointBrush);

}

void DrawClockPointer(HDC hDC)

{

int nHour, nMin, nSec;

GetCurTime(nHour, nMin, nSec);

int x1, y1, x2, y2;

//Draw Hour Pointer

HPEN hHourPen = ::CreatePen(PS_SOLID, 20, RGB(0, 0, 0));

HPEN hOldPen = (HPEN)::SelectObject(hDC, hHourPen);

int nRadius = 500 - 240;

x1 = (int)(nRadius * cos(PI / 2 - (2 * nHour * 5 * PI + nMin * PI / 6) / 60));

y1 = (int)(nRadius * sin(PI / 2 - (2 * nHour * 5 * PI + nMin * PI / 6) / 60));

nRadius = 40;

x2 = (int)(nRadius * cos(3 * PI / 2 - (2 * nHour * 5 * PI + nMin * PI / 6) / 60));

y2 = (int)(nRadius * sin(3 * PI / 2 - (2 * nHour * 5 * PI + nMin * PI / 6) / 60));

::MoveToEx(hDC, x1, y1, NULL);

::LineTo(hDC, x2, y2);

//Draw minute pointer

HPEN hMinPen = ::CreatePen(PS_SOLID, 12, RGB(0, 0, 0));

::SelectObject(hDC, hMinPen);

::DeleteObject(hHourPen);

nRadius = 500 - 140;

x1 = (int)(nRadius * cos(PI / 2 - (2 * nMin * PI) / 60));

y1 = (int)(nRadius * sin(PI / 2 - (2 * nMin * PI) / 60));

nRadius = 80;

x2 = (int)(nRadius * cos(3 * PI / 2 - (2 * nMin * PI) / 60));

y2 = (int)(nRadius * sin(3 * PI / 2 - (2 * nMin * PI) / 60));

::MoveToEx(hDC, x1, y1, NULL);

::LineTo(hDC, x2, y2);

//Draw Second pointer

::SelectObject(hDC, hOldPen);

::DeleteObject(hMinPen);

nRadius = 500 - 75;

x1 = (int)(nRadius * cos(PI / 2 - (2 * nSec * PI) / 60));

y1 = (int)(nRadius * sin(PI / 2 - (2 * nSec * PI) / 60));

x2 = 0;

y2 = 0;

::MoveToEx(hDC, x1, y1, NULL);

::LineTo(hDC, x2, y2);

}

void DrawClock(HDC hDC)

{

HDC hMemDC = ::CreateCompatibleDC(hDC);

RECT rc;

GetWindowRect(&rc);

SetMapMode(hMemDC, MM_ISOTROPIC);

SetWindowExtEx(hMemDC, 1000, 1000, NULL);

SetViewportOrgEx(hMemDC, (rc.right - rc.left) / 2, (rc.bottom - rc.top) / 2, NULL);

SetViewportExtEx(hMemDC, rc.right - rc.left, - (rc.bottom - rc.top), NULL);

HBITMAP hBitmap = ::CreateCompatibleBitmap(hDC, rc.right - rc.left, rc.bottom - rc.top);

HBITMAP hOldBitmap = (HBITMAP)::SelectObject(hMemDC, hBitmap);

DrawClockSurface(hMemDC);

DrawClockPointer(hMemDC);

::BitBlt(hDC, -500, -500, 1000, 1000, hMemDC, -500, -500, SRCCOPY);

SelectObject(hMemDC, hOldBitmap);

::DeleteObject(hBitmap);

::DeleteDC(hMemDC);

return;

}

void GetCurTime(int& nHour, int& nMin, int& nSec)

{

struct tm* tmCurrent;

time_t t;

t = time(NULL);

tmCurrent = localtime(&t);

nHour = tmCurrent->tm_hour;

nMin = tmCurrent->tm_min;

nSec = tmCurrent->tm_sec;

return;

}

};

int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR, int )

{

_Module.Init( NULL, hInstance );

CClockWindow wnd;

wnd.Create( NULL, CWindow::rcDefault, _T("ClockToy"),

WS_POPUP );

//wnd.ModifyStyleEx(0,WS_EX_TRANSPARENT /*| WS_EX_LAYERED*/);

CRgn rgn;

rgn.CreateEllipticRgn(0, 0, 180, 180);

wnd.SetWindowRgn(rgn.m_hRgn, TRUE);

wnd.SetWindowPos(HWND_TOPMOST, 0, 0, 180, 180, SWP_NOMOVE);

wnd.MoveWindow(100, 100, 180, 180, TRUE);

::SetLayeredWindowAttributes(wnd.m_hWnd, RGB(255, 255, 255), 0, LWA_COLORKEY);

wnd.CenterWindow();

wnd.ShowWindow(SW_SHOW);

wnd.UpdateWindow();

MSG msg;

while( GetMessage( &msg, NULL, 0, 0 ) ){

TranslateMessage( &msg );

DispatchMessage( &msg );

}

_Module.Term();

return (int)msg.wParam;

}

contact me at younker@yeah.net

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有