討論區快速選單
知識庫快速選單
政府補助!資策會APP就業班 政府補助!學嵌入式+物聯網 下載Alexa Toolbar讓你上網更有趣
[ 回上頁 ] [ 討論區發言規則 ]
MFC不規則視窗疑問請教~
更改我的閱讀文章字型大小
作者 : chengreg(chengreg)
[ 貼文 19 | 人氣 8506 | 評價 100 | 評價/貼文 5.26 | 送出評價 1 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2009/4/29 上午 11:00:28
請教各位前輩
小弟目前正有一個需求是改變SDI主視窗之樣式
所以小弟做了個實驗,但是發現了些問題
小弟認為應當是自己本身觀念上的問題,但遲遲無法想透
所已請各位前輩給予指導,與提供見解, 萬分感謝

首先!
小弟的實驗使用 VS2005 MFC 直接使用精靈建立 SDI 視窗

步驟二 :
建立一個 class CDib : public CObject
建立 function
void CDib::SetWindowsRGN(HWND hWnd,CDC *pDC,Uint nID)
{
CBitmap myBitmap,*pOldBitmap;
myBitmap.LoadBitmapW(nID);

CDC memDC;
memDC.CreateCompatibleDC(pDC);
pOldBitmap = memDC.SelectObject(&myBitmap);

CRect rectWnd;
::GetWindowRect(hWnd,&rectWnd);

CRgn rgnWnd,rgnTemp;
rgnWnd.CreateRectRgn(0,0,rectWnd.Width()-1,rectWnd.Height()-1);

for(int iWidth=0;iWidth <= rectWnd.Width() ; iWidth++)
{
for(int iHeight=0;iHeight <= rectWnd.Height() ; iHeight++)
{
if(memDC.GetPixel(iWidth,iHeight) == RGB(0,255,0))
{
rgnTemp.CreateRectRgn(iWidth,iHeight,iWidth+1,iHeight+1);
rgnWnd.CombineRgn(&rgnWnd,&rgnTemp,RGN_XOR);

rgnTemp.DeleteObject();
}
}
}

memDC.SelectObject(pOldBitmap);
::SetWindowRgn(hWnd,(HRGN)rgnWnd,true);

}

主要目的就是把 RGB(0,255,0) 綠色部分給剔除 ,然後設定WindowRgn為不規則形狀
OK~以上的方法皆正常的把視窗給裁成不規則的樣式
但是這也只是不規則的"視窗",白白一片,並沒有圖案

步驟三:(MainFrm.cpp)
小弟於 int CMainFrame::OnCreate(LPCREATEstruct lpCreateStruct)
執行了 mDib.SetWindowsRGN(this->m_hWnd,this->GetDC(),IDB_BITMAP1);

再者攔截 OnEraseBkgnd 並加入程式碼以求顯示圖片
BOOL CMainFrame::OnEraseBkgnd(CDC* pDC)
{
// TODO: 在此加入您的訊息處理常式程式碼和 (或) 呼叫預設值
pDC->SetBkColor(TRANSPARENT);
CRect rectWnd;
::GetWindowRect(this->m_hWnd,&rectWnd);
CDC memDC;
CBitmap myBitmap,*pOldBitmap;
myBitmap.LoadBitmapW(IDB_BITMAP1);
memDC.CreateCompatibleDC(pDC);
pOldBitmap = memDC.SelectObject(&myBitmap);
pDC->BitBlt(0,0,rectWnd.Width(),rectWnd.Height(),&memDC,0,0,SRCCOPY);

memDC.SelectObject(pOldBitmap);

return true;

//return CFrameWnd::OnEraseBkgnd(pDC);
}

但是 發現了幾個問題
1.首先小弟SetWindowRgn後,整個視窗包含工具列,皆被剪裁成不規則狀
2.執行後圖型沒有呈現,最主要是因為小弟沒於OnPaint再度做處理
3.但是拉動畫面縮小/放大(改變大小)會觸發OnEraseBkgnd則發現畫面出現了
   只是呈現的位置有問題,圖片呈現的起始位置為 WindowsClientArea內
   無法與剪裁的Rgn對應起來 T_T....

以上狀況,懇請前輩指導,是否小弟的架構有問題
還是不應當於 CMainFrame內呼叫 ??
那怎會圖片呈現於 ClientArea內 , 但是SetWindowsRgn 卻是整個 Window(包含工具列都裁掉)

以上疑問~請前輩給予指導
再次感謝~
作者 : chiuinan2(青衫)討論區板主 Visual C++ .NET卓越專家VC++一代宗師Visual Basic優秀好手資訊類作業求救卓越專家一般曠世奇才程式設計甘苦談優秀好手C++ Builder優秀好手上班族的哈拉園地優秀好手C++頂尖高手Assembly優秀好手貼文超過3000則人氣指數超過150000點
[ 貼文 3727 | 人氣 170106 | 評價 34340 | 評價/貼文 9.21 | 送出評價 125 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2009/4/30 下午 09:04:00
>1.首先小弟SetWindowRgn後,整個視窗包含工具列,皆被剪裁成不規則狀

SetWindowRgn本來就作用在整個視窗啊... 其座標是相對於視窗左上角 (不是Client區).

>3.但是拉動畫面縮小/放大(改變大小)會觸發OnEraseBkgnd則發現畫面出現了
> 只是呈現的位置有問題,圖片呈現的起始位置為 WindowsClientArea內
> 無法與剪裁的Rgn對應起來 T_T....

OnPaint或OnEraseBkgnd繪製的座標, 是相對於Client區左上角. 要對齊的話, 你必須自行修改SetWindowRgn的座標, 或是修改繪製時的座標. Client區左上角與視窗左上角的偏移差, 可用GetWindowRect取得視窗左上角的螢幕座標, 再用ClientToScreen以參數(0,0)執行得到Client區左上角的螢幕座標, 兩者相減便是了.
 板主 : 青衫 , Raymond
 > Visual C++ - 討論區
 - 最近熱門問答精華集
 - 全部歷史問答精華集
 - Visual C++ - 知識庫
  ■ 全站最新Post列表
  ■ 我的文章收藏
  ■ 我最愛的作者
  ■ 全站文章收藏排行榜
  ■ 全站最愛作者排行榜
  ■  月熱門主題
  ■  季熱門主題
  ■  熱門主題Top 20
  ■  本區Post排行榜
  ■  本區評價排行榜
  ■  全站專家名人榜
  ■  全站Post排行榜
  ■  全站評價排行榜
  ■  全站人氣排行榜
 請輸入關鍵字 
  開始搜尋
 
Top 10
評價排行
Visual C++
1 青衫 10990 
2 Raymond 9820 
3 Clier 7630 
4 小約翰 2500 
5 Cog 2030 
6 coco 1790 
7 aming 1410 
8 牧童哥 1400 
9 r2109 1380 
10 Akira 1350 
Visual C++
  專家等級 評價  
  一代宗師 10000  
  曠世奇才 5000  
  頂尖高手 3000  
  卓越專家 1500  
  優秀好手 750  
Microsoft Internet Explorer 6.0. Screen 1024x768 pixel. High Color (16 bit).
2000-2014 程式設計俱樂部 http://www.programmer-club.com.tw/
0.140625