程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> 關於VC++ >> QQ2006界面編程之雞蛋裡挑骨頭

QQ2006界面編程之雞蛋裡挑骨頭

編輯:關於VC++

2007新的一年即將來臨,新版本的QQ估計也要跟我們相見。在此獻上本人寫於8月份的一個練習程序。主要是希望騰訊做界面的同志能否把創建異形窗體函數 SetWindowRgn 放到合適的位置,別讓拖動窗體改變大小時出現用做 MASK 的紫色區域;再者與大家分享不指定窗體風格 WS_THICKFRAME(對於對話框,相當指定其屬性 Border 為 Resizing ),用代碼實現窗體拖放,任意改變其尺寸。

一、SetWindowRgn的合適位置

1、在void C**Dlg::OnPaint()裡調用SetWindowRgn,可以在內存畫圖完畢准備顯示到屏幕前調用,如下:

void C**Dlg::OnPaint()
{
  if (IsIconic())
  {
   CPaintDC dc(this);
   ...
  }
  else
  {
   CPaintDC dc(this); // 用於繪制的設備上下文
   CRect rcClient;
   GetClientRect(&rcClient);
   //構造內存DC,用於畫圖
   CDC m_MemDC;
   m_MemDC.CreateCompatibleDC(&dc);
   CBitmap btScreen;
   btScreen.CreateCompatibleBitmap(&dc, rcClient.Width(), rcClient.Height());
   m_MemDC.SelectObject(&btScreen);
   btScreen.DeleteObject();
   //這裡畫圖
   ...
   //創建不規則窗體
   ChangeWindowRgn(&m_MemDC);//這裡面調用了SetWindowRgn
   //畫到顯示器上
   dc.BitBlt(rcClient.left, rcClient.top, rcClient.Width(), rcClient.Height(), &m_MemDC, 0, 0, SRCCOPY);
   m_MemDC.DeleteDC();
  }
}
void C**Dlg::ChangeWindowRgn(CDC *pDC)
{
  COLORREF col = RGB(255,0,255);
  CRect rcClient;
  GetClientRect (rcClient);
  CRgn rgn;
  rgn.CreateRectRgn (0, 0, rcClient.Width(), rcClient.Height());
  ...
  SetWindowRgn (rgn, TRUE);
}

2、在void C**Dlg::OnShowWindow()裡調用SetWindowRgn, 如下:

void C**Dlg::OnShowWindow(BOOL bShow, UINT nStatus)
{
  CWnd::OnShowWindow(bShow, nStatus);
  // TODO: 在此處添加消息處理程序代碼
  if(bShow)
  {
   CRect rc;
   this->GetClientRect(&rc);
   CRgn rgnMain;
   rgnMain.CreateRoundRectRgn(0, 0, rcClient.Width(), rcClient.Height());
   ...
   SetWindowRgn( rgnMain, TRUE );
  }
}

二、手動做“Resizing對話框”

該思路啟發於徐景周的精靈特效窗體。要想點擊窗體客戶區不放能移動窗體,傳統的做法是模擬消息點擊標題。

void C**Dlg::OnLButtonDown(UINT nFlags, CPoint point)
{
  // TODO: 在此添加消息處理程序代碼
  PostMessage(WM_NCLBUTTONDOWN,HTCAPTION,0);
  CDialog::OnLButtonDown(nFlags, point);
}

這樣很方便實現效果。但不足是窗體被移到屏幕上方,大部分在屏幕所能顯示以外以後放開鼠標,窗體會自動向下對齊。徐景周的精靈特效窗體用了SetTimer和MoveWindow結合使用,這樣窗體想被移到哪裡都可以。正因為如此,讓我想到拖放窗體的好思路。當然我們完全可以利用窗體風格WS_THICKFRAME,讓系統來為我們做事。

但是如果我們要指定窗體某個部位可以拖放窗體時,像QQ切換主題後,拖放很不方便。可以拖放的區域不是最左,最右,最上,最下,沒有別的地方可以點擊拖放窗體了。

如何實現,簡單說就是在鼠標按下時判斷是否點在規定區域內,是的話啟動記時器。然後在記時器裡面定時器裡面對光標判斷當前位置與之前位置,從而調用MoveWindow讓窗體朝響應方向拉伸或收縮。代碼較瑣碎,請見例子。

void C**Dlg::OnLButtonDown(UINT nFlags, CPoint point)
{
  CRect rc(*,*,*,*);
  if(rc.PtInRect(point))
  {
   SetTimer(1,20,NULL);//啟動記時器
   return;
  }
  CDialog::OnLButtonDown(nFlags, point);
}
void C**Dlg::OnTimer(UINT_PTR nIDEvent)
{
  // TODO: 在此添加消息處理程序代碼和/或調用默認值
  switch(nIDEvent)
  {
   case(1):
   {
    CRect rcW;
    POINT point;
    GetWindowRect(rcW);//
    //實現拖動時窗體跟著右下角拉伸
    ::GetCursorPos(&point); //得到“當前位置”
    if(point.y<rcW.bottom-400)
    {
     MoveWindow(m_rcCurRect.left ,point.y-m_ptCurPoint.y, rcW.Width(),
m_rcCurRect.bottom-(point.y-m_ptCurPoint.y), true);
     CRect rc;
     GetWindowRect(rc);
     m_rcCurRect = rc;//保存“之前位置”
    }
    Invalidate();
   }
   break;
    ...
   Default:
    break;
  }
  Dialog::OnTimer(nIDEvent);
}

代碼在Visual2005下編譯,在WindowXP運行通過。預覽圖如下:

預覽圖

  1. 上一頁:
  2. 下一頁:
欄目導航
Copyright © 程式師世界 All Rights Reserved