如是大家细心的话,在使用“Virtual Drive Manager”也就是一个非常小的虚拟光驱的时候,在它的设置里有一个“启用窗口的 Alpha 混合半透明效果”功能。这个功能很友善,就是在你想拖动窗体的时候,窗体会自动的渐隐,等到你松开窗口的时候,窗体就恢复到不透明的状态。下面是 该功能的截图今天要做的就是让我们的程序也实现这个功能。
OK先分析一下它的功能。
1.当点击标题栏的时候,让窗口半透明
2.当松开标题栏的时候,窗口自动恢复不透明的状态
明天了原理之后我们就可以很简单的来实现这个功能了,点击标题栏我们可以用“ON_WM_NCLBUTTONDOWN”这个事件来触发。当松开标题栏的时候可以使用“ON_WM_NCLBUTTONUP”事件。但现在有问题了,在我写的过程中“ON_WM_NCLBUTTONUP”当松开对标题栏的点击时程序不会触发“ON_WM_NCLBUTTONUP”事件。所以这程序就渐接的转换为使程序响应“ON_WM_NCLBUTTONUP”事件。
值得说的是可以用ON_WM_SYSCOMMAND事件来得到“ON_WM_NCLBUTTONUP” ,好了,下面让我们来实现这个小程序吧
首先先建立一个“基本对话框”程序。有没有关于对话框都一样,如是有的话就省略后面写ON_WM_SYSCOMMAND这个事件了。OK,我就建立一个不要关于对话框的程序
首先先添加“ON_WM_NCLBUTTONDOWN”,这个事件在VC6.0是没有办法找到怎么添加的,所以我们要手动添加。在
- BEGIN_MESSAGE_MAP(CMyDlg, CDialog)
- //{{AFX_MSG_MAP(CMyDlg)
- ......
- ON_WM_NCLBUTTONDOWN() //添加鼠标按下标题栏时的事件
- ......
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
添加好之后再添加对应的函数响应
- //
- // 添加渐隐函数——按下时
- void down(void)
- {
- for (int m_int=255;m_int>=128;m_int-=7){
- SetWindowLong(AfxGetMainWnd()->m_hWnd,GWL_EXSTYLE,
- GetWindowLong(AfxGetMainWnd()->m_hWnd,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(AfxGetMainWnd()->m_hWnd,0,m_int,2);
- FreeLibrary(hInst);
- }
- Sleep(10);
- }
- }
- //
- // 响应点击标题栏函数
- void CMyDlg::OnNcLButtonDown(UINT nHitTest, CPoint point)
- {
- if (nHitTest == HTCAPTION)
- hDownThread=CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)down,NULL,NULL,NULL);
- CDialog::OnNcLButtonDown(nHitTest, point);
- }
再在对应的Dlg.h中声明 OnNcLButtonDown 函数为事件函数
- afx_msg void OnNcLButtonDown(UINT nHitTest, CPoint point);
这样编译一下就可以现在点击标题栏时的半透明窗口了。
OK,下面以相同的方法添加“ON_WM_NCLBUTTONUP”和“ON_WM_SYSCOMMAND” 由于内容基本一样,所以就不写打了,直接给代码
- //
- // ON_WM_SYSCOMMAND事件响应函数
- void CMyDlg::OnSysCommand(UINT nID, LPARAM lParam)
- {
- CDialog::OnSysCommand(nID, lParam);
- // 手动添加WM_NCLBUTTONUP事件
- if((nID&0xFFF0)==SC_MOVE) PostMessage(WM_NCLBUTTONUP,nID,lParam);
- }
- HANDLE hDownThread=NULL; //按下时的线程句柄
- //
- // 添加渐隐函数——松开时
- void Up(void)
- {
- WaitForSingleObject(hDownThread,INFINITE);
- for (int m_int=128;m_int<=255;m_int+=7){
- SetWindowLong(AfxGetMainWnd()->m_hWnd,GWL_EXSTYLE,
- GetWindowLong(AfxGetMainWnd()->m_hWnd,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(AfxGetMainWnd()->m_hWnd,0,m_int,2);
- FreeLibrary(hInst);
- }
- Sleep(10);
- }
- }
- //
- // 响应松开标题栏时的函数
- void CMyDlg::OnNcLButtonUp(UINT nHitTest, CPoint point)
- {
- CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)Up,NULL,NULL,NULL);
- CDialog::OnNcLButtonUp(nHitTest, point);
- }
OK,编译一下看看自己的程序是什么样子的吧,是不是感觉它很“温和”呢。呵呵。。
下面是我的程序截图