霍普雷霆同人漫:如何实现透明窗口

来源:百度文库 编辑:偶看新闻 时间:2024/05/01 09:00:25

如何实现透明窗口

                                      

如何实现透明窗口

使用MFC的AppWizard生成一个基于对话框的工程,删除Didalog上的所有控件,并设置其附加属性Extended Styles为 Tool Window。

使用SetLayeredWindowAttributes可以方便的制作透明窗体,此函数在w2k以上才支持,而且如果希望直接使用的话,可能需要下载最新的SDK。不过此函数在w2k的user32.dll里有实现,所以如果你不希望下载巨大的sdk的话,可以直接使用GetProcAddress获取该函数的指针。

 

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


Windows NT/2000/XP: Included in Windows 2000 and later.
Windows 95/98/Me: Unsupported.(注意了,在win9x里没法使用的)
Header: Declared in Winuser.h; include Windows.h.
Library: Use User32.lib.

一些常量: 

WS_EX_LAYERED = 0x80000;
LWA_ALPHA = 0x2;
LWA_COLORKEY=0x1;  

其中dwFlags有LWA_ALPHA和LWA_COLORKEY  LWA_ALPHA被设置的话,通过bAlpha决定透明度.  LWA_COLORKEY被设置的话,则指定被透明掉的颜色为crKey,其他颜色则正常显示.  要使使窗体拥有透明效果,首先要有WS_EX_LAYERED扩展属性(旧的sdk没有定义这个属性,所以可以直接指定为0x80000).

例子代码:BOOL CFloatDlgDlg::OnInitDialog()

{

CDialog::OnInitDialog();

///////////////////////////控制窗体大小和位置/////////////////////////////////////////////

CRect rect;

CWnd *pWnd = this->GetDesktopWindow();

pWnd->GetWindowRect(&rect);

this->MoveWindow(rect.left + rect.Width() - 200, rect.top + 100, 42, 42);

SetWindowPos(&wndTopMost,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);

// Add "About..." menu item to system menu.

// IDM_ABOUTBOX must be in the system command range.

ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);

ASSERT(IDM_ABOUTBOX < 0xF000);

CMenu* pSysMenu = GetSystemMenu(FALSE);

if (pSysMenu != NULL)

{

CString strAboutMenu;

strAboutMenu.LoadString(IDS_ABOUTBOX);

if (!strAboutMenu.IsEmpty())

{

pSysMenu->AppendMenu(MF_SEPARATOR);

pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);

}

}

// Set the icon for this dialog. The framework does this automatically

// when the application’s main window is not a dialog

SetIcon(m_hIcon, TRUE); // Set big icon

SetIcon(m_hIcon, FALSE); // Set small icon

// TODO: Add extra initialization here

////////////////////////以下实现窗体的透明///////////////////////////////////

//加入WS_EX_LAYERED扩展属性

SetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE,

GetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE)^0x80000);

HINSTANCE hInst = LoadLibrary("User32.DLL");

if(hInst)

{

typedef BOOL (WINAPI *MYFUNC)(HWND,COLORREF,BYTE,DWORD);

MYFUNC fun = NULL;

//取得SetLayeredWindowAttributes函数指针

fun=(MYFUNC)GetProcAddress(hInst, "SetLayeredWindowAttributes");

if(fun)fun(this->GetSafeHwnd(),0,128,2);

FreeLibrary(hInst);

}

//////////////////////////////////////////////////////////////////////////////////

ModifyStyle( WS_CAPTION, WS_MINIMIZEBOX, SWP_DRAWFRAME );//设置图标

m_bmpBackground.LoadBitmap(IDB_FLOAT);

return TRUE; // return TRUE unless you set the focus to a control

}

如何实现浮动窗口的拖动

一般的窗体,只有鼠标位于非客户区是,才可拖动。因此,只要我们将客户区“变”为“非客户区”不就可以拖动了了吗!真是一个让人惊奇的发现!:),可是问题来了,非客户区无法加载快捷菜单,我们如何解决这一问题呢,那我们想想什么动作触发快捷菜单呢?对了,WM_RBUTTONDOWN,WM_RBUTTONUP,那拖动呢?哈哈,是WM_LBUTTONDOWN,OK,那就有方法解决了,那就是在鼠标左键按下时才将客户区“变”为“非客户区”。重载OnLButtonDown(UINT nFlags, CPoint point) ,OnLButtonUp(UINT nFlags, CPoint point),OnMouseMove(UINT nFlags, CPoint point),OnNcHitTest(CPoint point):

void CFloatDlgDlg::OnLButtonDown(UINT nFlags, CPoint point)

{

// TODO: Add your message handler code here and/or call default

m_oldpoint = point;

SetCapture();

drag = TRUE;

CDialog::OnLButtonDown(nFlags, point);

}