MFC模拟360悬浮窗加速球窗口
1,目標(biāo)
實(shí)現(xiàn)類似360懸浮窗口這樣的效果,當(dāng)窗口在屏幕邊緣時(shí),鼠標(biāo)移開,就自動(dòng)向邊緣隱藏,鼠標(biāo)放上去,就又平滑顯示出來。
正常狀態(tài):
邊緣自動(dòng)隱藏:
2,原理
首先是實(shí)現(xiàn)圓角或橢圓這種不規(guī)則形狀的窗口,可以參考另一篇文章:
MFC實(shí)現(xiàn)不規(guī)則窗口
?然后需要給沒有標(biāo)題欄的窗口增加拖拽移動(dòng)的功能,這個(gè)就是自己手動(dòng)發(fā)送一個(gè)消息,使windows認(rèn)為鼠標(biāo)在標(biāo)題條上
對于窗口的移動(dòng)顯示隱藏,使用了定時(shí)器。
其中有一些做判斷的函數(shù),如判斷在窗口在屏幕某個(gè)邊緣,判斷鼠標(biāo)是否在窗口內(nèi)部等。
3,實(shí)現(xiàn)
①新建MFC對話框程序Test360.去掉默認(rèn)控件和屬性中的邊框。參考上面所說的文章實(shí)現(xiàn)一個(gè)帶圓角及背景圖片的窗口。
由于這里還是截圖然后用PS簡單選擇了個(gè)范圍,所以還有毛邊,若是有美工原圖或PS仔細(xì)些,是沒問題的。
②給Dlg類CTest360Dlg添加一條消息響應(yīng)OnLButtonDown,在其中傳送WM_NCLBUTTONDOWN消息,達(dá)到拖動(dòng)效果。
void CTest360Dlg::OnLButtonDown(UINT nFlags, CPoint point) {CDialog::OnLButtonDown(nFlags, point);// 實(shí)現(xiàn)拖動(dòng)窗口// 發(fā)送WM_NCLBUTTONDOWN消息// 使Windows認(rèn)為鼠標(biāo)在標(biāo)題條上// 或SendMessage(WM_SYSCOMMAND,SC_MOVE | HTCAPTION,0); PostMessage(WM_NCLBUTTONDOWN,HTCAPTION,MAKELPARAM(point.x, point.y)); }③添加幾個(gè)判斷窗口是否在屏幕邊緣的函數(shù): //是否靠近屏幕左邊緣 BOOL CTest360Dlg::NearLeftBorder() {CRect rc;GetWindowRect(rc);//窗口左邊界在屏幕左邊界20像素內(nèi)都算“靠近”if (rc.left < 20){return TRUE;}return FALSE; } //是否靠近屏幕上邊緣 BOOL CTest360Dlg::NearUpBorder() {CRect rc;GetWindowRect(rc);if(rc.top<20){return TRUE;}return FALSE; } //是否靠近右邊緣 BOOL CTest360Dlg::NearRightBorder() {CRect rc;GetWindowRect(rc);int nWidth = GetSystemMetrics(SM_CXSCREEN);if (rc.left>nWidth - rc.Width()){return TRUE;}return FALSE; }
④判斷鼠標(biāo)是否在窗口內(nèi)。 BOOL CTest360Dlg::MouseInWnd() {CRect rc;GetWindowRect(rc);POINT pt;GetCursorPos(&pt);if (PtInRect(&rc,pt)){return TRUE;}return FALSE; }⑤定義一個(gè)定時(shí)器, #define TIMER_MOVE 1在CTest360Dlg::OnInitDialog()中啟動(dòng): BOOL CTest360Dlg::OnInitDialog() {CDialog::OnInitDialog();// 設(shè)置此對話框的圖標(biāo)。當(dāng)應(yīng)用程序主窗口不是對話框時(shí),框架將自動(dòng)// 執(zhí)行此操作SetIcon(m_hIcon, TRUE); // 設(shè)置大圖標(biāo)SetIcon(m_hIcon, FALSE); // 設(shè)置小圖標(biāo)//設(shè)置窗口形狀SetRegion(GetDC(),IDB_BITMAP_360RGN,RGB(0,0,0));//初始時(shí)居中CenterWindow();//設(shè)置定時(shí)器,處理懸浮窗的顯隱移動(dòng)SetTimer(TIMER_MOVE,10,NULL);return TRUE; }
處理如下: void CTest360Dlg::OnTimer(UINT_PTR nIDEvent) {if (nIDEvent == TIMER_MOVE){//鼠標(biāo)按著的,就怎么都不移動(dòng)if (GetKeyState(VK_LBUTTON)<0){return;}//靠近屏幕上邊緣if (NearUpBorder()){//根據(jù)鼠標(biāo)動(dòng)作進(jìn)行窗口的移動(dòng)(鼠標(biāo)進(jìn)入?yún)^(qū)域就向下平移顯示,鼠標(biāo)離開就向上平移隱藏)MoveUp();return;}//靠近屏幕左邊緣if (NearLeftBorder()){//根據(jù)鼠標(biāo)動(dòng)作進(jìn)行窗口的移動(dòng)(鼠標(biāo)進(jìn)入?yún)^(qū)域就向右平移顯示,鼠標(biāo)離開就向左平移隱藏)MoveLeft();return;}//靠近屏幕右邊緣if (NearRightBorder()){//根據(jù)鼠標(biāo)動(dòng)作進(jìn)行窗口的移動(dòng)(鼠標(biāo)進(jìn)入?yún)^(qū)域就向左平移顯示,鼠標(biāo)離開就向右平移隱藏)MoveRight();return;}}CDialog::OnTimer(nIDEvent); }
其中GetKeyState先強(qiáng)行過濾掉鼠標(biāo)按下,讓這種情況不移動(dòng)。避免剛拖動(dòng)窗口到屏幕邊緣時(shí)鼠標(biāo)還沒松開就直接開始移動(dòng)了。
3個(gè)Move函數(shù),是真正按像素移動(dòng)窗口的地方,包括來回(出屏幕和進(jìn)屏幕)。原理是一樣的,看明白一個(gè)就OK了。
void CTest360Dlg::MoveUp() {CRect rc;GetWindowRect(rc);//鼠標(biāo)進(jìn)入則下移,顯示出來if(MouseInWnd()){int height = rc.Height();if (rc.top>=0){rc.top = 0;}else{rc.top++;}rc.bottom = rc.top + height;MoveWindow(rc);}//鼠標(biāo)在別處,窗口就往上移出屏幕else{int height = rc.Height();//窗口向上移動(dòng)一像素,如果快隱藏(露20)就不移了if (rc.top<= 20 - height){rc.top = 20 - height;ShowWindow(SW_HIDE);m_upDlg->m_Test360Dlg = this;m_upDlg->DoModal();}else{rc.top--;}rc.bottom = rc.top + height;MoveWindow(rc);} } void CTest360Dlg::MoveLeft() {CRect rc;GetWindowRect(rc);//鼠標(biāo)進(jìn)入則下移,顯示出來if(MouseInWnd()){int width = rc.Width();if (rc.left>=0){rc.left = 0;}else{rc.left++;}rc.right = rc.left + width;MoveWindow(rc);}//鼠標(biāo)在別處,窗口就往上移出屏幕else{int width = rc.Width();//窗口向左移動(dòng)一像素,如果快隱藏(留20像素)就不移了if (rc.left<= 20 - width){rc.left = 20 - width;}else{rc.left--;}rc.right = rc.left + width;MoveWindow(rc);} } void CTest360Dlg::MoveRight() {CRect rc;GetWindowRect(rc);int sysWidth = GetSystemMetrics(SM_CXSCREEN);//鼠標(biāo)在窗口內(nèi)則窗口左移,顯示出來if(MouseInWnd()){int width = rc.Width();if (rc.left<= sysWidth - width){rc.left = sysWidth - width;}else{rc.left--;}rc.right = rc.left + width;MoveWindow(rc);}//鼠標(biāo)沒在窗口上,窗口就往右移出屏幕else{int width = rc.Width();//窗口向右移動(dòng)一像素,如果快隱藏了(還留20像素)就不移了if (rc.left>= sysWidth - 20){rc.left = sysWidth - 20;}else{rc.left++;}rc.right = rc.left + width;MoveWindow(rc);}}對MoveUp做說明:當(dāng)Timer中判斷到窗口在屏幕上邊緣時(shí),進(jìn)入MoveUp,如果此時(shí)鼠標(biāo)進(jìn)入窗口內(nèi),窗口就往下方移動(dòng)直到完全顯示;如果鼠標(biāo)離開窗口,那么窗口會(huì)立即往上隱藏,直到留下一小截。 360官方軟件現(xiàn)在是換了個(gè)半圓形的窗口“趴”在屏幕邊上。這里主要是模擬觸發(fā)移動(dòng)的效果。
4,效果
幾張截圖
左側(cè):
上側(cè):
右側(cè):
5,源碼
MFC模擬360懸浮窗加速球Test360_VS2008工程.rar
總結(jié)
以上是生活随笔為你收集整理的MFC模拟360悬浮窗加速球窗口的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 用python写helloworld_P
- 下一篇: go 函数名之前括号中的内容_2020