VS2010,单文档,基类为CFormView.想在中间的对话框镂空处一个正方体出来,代码如下:
::GetWindowRect(m_hWnd,&m_rect);//镂空     //以下为不加ScreenToClient(&m_rect)
    //width = m_rect.Width();//500
    //height = m_rect.Height();//484
    //int right = m_rect.right;//662
    //int left = m_rect.left;  //162
    //int top = m_rect.top;   //43
     //int bottom = m_rect.bottom; //527            //以下为加ScreenToClient(&m_rect);坐标
    ScreenToClient(&m_rect); width = m_rect.Width();//500
height = m_rect.Height();//484
int right = m_rect.right;//492
int left = m_rect.left;  //-8
int top = m_rect.top;   //-50
int bottom = m_rect.bottom; //434

CRgn wndRgn;
//上半部
wndRgn.CreateRectRgn(0,0, m_rect.Width(),m_rect.top+230);//可赋值,这样可少画一个rgnTemp
CRgn rgnTemp; //保存临时region

//左半部
rgnTemp.CreateRectRgn(0,0, m_rect.left+40, m_rect.Height());
wndRgn.CombineRgn(&wndRgn, &rgnTemp, RGN_OR);
rgnTemp.DeleteObject();
//右半部
rgnTemp.CreateRectRgn(m_rect.Width()-40, 0, m_rect.Width(),m_rect.Height());//有问题!!!
wndRgn.CombineRgn(&wndRgn, &rgnTemp, RGN_OR);
rgnTemp.DeleteObject();
//下半部
rgnTemp.CreateRectRgn(0, m_rect.Height() - 140, m_rect.Width(),m_rect.Height());
wndRgn.CombineRgn(&wndRgn, &rgnTemp, RGN_OR);
rgnTemp.DeleteObject(); //SetWindowRgn(static_cast<HRGN>(rgn1.GetSafeHandle()), TRUE);
SetWindowRgn(wndRgn,TRUE);//!!!
wndRgn.DeleteObject();
我现在遇到的问题是
1)窗体可以镂空,但是一拖右边的对话框的边放大,就会出现边缘不见的情况,尺寸大小也有问题。而拖左边则不会出现这种请况。
2)绘制了上半部后,我原来的标题栏那些都受到了影响,都变黑了,也覆盖了我标题栏上的一些按钮。我只是想在正中间镂空,不想影响其它地方。
求解

解决方案 »

  1.   

    从资源拖一个picture(static),属性frame。
      

  2.   

    就是说要运行一个程序,这个程序的窗口大小就是你挖的‘洞’,这个不需要挖‘洞’,你把启动的程序窗口移到(MoveWindow)你的位置就行了吧?
      

  3.   

    是用的这个,但是出现了我最开始说的两个问题。
    向大哥如果有时间,可以建个工程试试。
    以下是我改进的代码,比较短。放在int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)下
    void CMainFrame::CreatRect()
    {
    SetWindowLong(m_hWnd, GWL_STYLE, GetWindowLong(m_hWnd, GWL_STYLE) 
            & (~(WS_CAPTION | WS_BORDER)));//不重绘边框和标题栏 CRgn WindowRgn;
    CRgn HoleRgn;
    CRect WindowRect;
    GetWindowRect(WindowRect);
    //ScreenToClient(WindowRect);
    //得到窗口形状
    BOOL bWindowSucceed = WindowRgn.CreateRectRgn(0,0,WindowRect.Width()+14,WindowRect.Height());
    ASSERT( bWindowSucceed == TRUE );
    //初始化洞口区域
    BOOL bHoleSucceeded = HoleRgn.CreateRectRgn(WindowRect.Width()/4,WindowRect.Height()/4,WindowRect.Width()*4/5,WindowRect.Height()*4/5);
    ASSERT( bHoleSucceeded == TRUE );
    //合并
    WindowRgn.CombineRgn(&HoleRgn,&WindowRgn,RGN_XOR);//RGN_XOR异或
    SetWindowRgn((HRGN)WindowRgn.m_hObject/*(HRGN)WindowRgn*/,true);
    //以下语句可还原
    //SetWindowRgn(NULL,true); WindowRgn.DeleteObject();
    HoleRgn.DeleteObject();
    }
      

  4.   

    不好意思
    刚刚一直没有仔细看代码
    我仔细看了一下你的帖子
    问题应该是这样的
    通过SetWindowRgn设置的窗体不支持拖拽改变大小
    也不支持最大化和还原了
    所以一般的处理方式是在OnSize中调用这段设置窗口的代码
    而且还有一个问题
    你应该设置MainFrame而不是针对子窗口操作
    你可以试一下
      

  5.   

    而且还有一个问题
    "你应该设置MainFrame而不是针对子窗口操作"
    这是什么意思呢?
      

  6.   

    MFC的文档视图结构都有一个MainFrame作为总的窗口框架
    你的工程里应该能看到
      

  7.   

    是的,我是写在CMainFrame::OnCreate里的。
    我把SetWindowRgn((HRGN)WindowRgn.m_hObject/*(HRGN)WindowRgn*/,true);
    写在OnSize里是要好些了。
    我是用的15楼的代码。就是先画一个完整的大的框,再画一个小的,不需要的框,异或下就可以。
    但是由此带来两个问题(原先也有)
    1)标题栏变黑了。
    2)双击标题栏,边框没了。
      

  8.   

    你把窗口都挖空了!
    要先GetWindowRgn再挖。
      

  9.   

    总觉得思路有问题:
    1。创建原程序时会用到,如"notepad.exe"
    // by creating process ***********************************
    BOOL GoNotePad(char *path,BOOL bWait=TRUE)
    {
    char pathexe[MAX_PATH];
    strcpy(pathexe,"notepad.exe ");
    strcat(pathexe,path);//pathname="notepad.exe ",
    STARTUPINFO sinfo;
    PROCESS_INFORMATION pinfo;
    memset (&sinfo,0,sizeof(STARTUPINFO));
    sinfo.cb=sizeof(STARTUPINFO);
    sinfo.dwFlags|=STARTF_USESHOWWINDOW;
    sinfo.wShowWindow=SW_SHOWNORMAL;//SW_SHOW;// SW_SHOWDEFAULT;
    //BOOL fsuccess=0;
    BOOL fsuccess=CreateProcess(NULL,//lpApplicationName
      pathexe, //lpCommanderLine
      NULL, //lpProcessAttributes
      NULL, //lpThreadAttributes
      FALSE, //bInheritHandles
      NORMAL_PRIORITY_CLASS,//dwCreationFlags
      NULL, //lpEnvironment
      NULL, //lpCurrentDirectory
      &sinfo, //lpStartupInfo
      &pinfo); //lpProcessInformation
    // wait for NotePad finishes
    if(fsuccess)
    {
    HANDLE hProcess=pinfo.hProcess;
    CloseHandle(pinfo.hThread);// close thread at once
    if (bWait)
    {
    if (WaitForSingleObject(hProcess,INFINITE)!=WAIT_FAILED)
    {
    DWORD dwExitCode;
    GetExitCodeProcess(hProcess,&dwExitCode);
    if (dwExitCode==STILL_ACTIVE) AfxMessageBox("NotePad still alive !");
    }
    }
    CloseHandle(pinfo.hProcess);
    }
    return(fsuccess);
    }
    2。
    typedef struct _STARTUPINFO { // si 
        DWORD   cb; 
        LPTSTR  lpReserved; 
        LPTSTR  lpDesktop; 
        LPTSTR  lpTitle; 
        DWORD   dwX; 
        DWORD   dwY; 
        DWORD   dwXSize; 
        DWORD   dwYSize; 

        DWORD   dwXCountChars; 
        DWORD   dwYCountChars; 
        DWORD   dwFillAttribute; 
        DWORD   dwFlags; 
        WORD    wShowWindow; 
        WORD    cbReserved2; 
        LPBYTE  lpReserved2; 
        HANDLE  hStdInput; 
        HANDLE  hStdOutput; 
        HANDLE  hStdError; 
    } STARTUPINFO, *LPSTARTUPINFO; 
    可以指定位置。
      

  10.   

    获得啥子了再挖啊?
    CRgn WindowRgn;
    CRgn HoleRgn;
    CRect WindowRect;
    GetWindowRect(WindowRect);
    //ScreenToClient(WindowRect);
    //得到窗口形状
    BOOL bWindowSucceed = WindowRgn.CreateRectRgn(0,0,WindowRect.Width()+14,WindowRect.Height());
    ASSERT( bWindowSucceed == TRUE );
    //初始化洞口区域
    BOOL bHoleSucceeded = HoleRgn.CreateRectRgn(WindowRect.Width()/4,WindowRect.Height()/4,WindowRect.Width()*4/5,WindowRect.Height()*4/5);
    ASSERT( bHoleSucceeded == TRUE );
    //合并
    WindowRgn.CombineRgn(&HoleRgn,&WindowRgn,RGN_XOR);//RGN_XOR异或
    //SetWindowRgn((HRGN)WindowRgn.m_hObject/*(HRGN)WindowRgn*/,true);
      

  11.   

    这是我给你做的,客户区只留下 1/32,其余挖空:
    void CBaoView::OnInitialUpdate()
    {
    CFormView::OnInitialUpdate();
    GetParentFrame()->RecalcLayout();
    ResizeParentToFit();
    //镂空
    CRect rc;
    GetClientRect(&rc); CRgn wndRgn;
    wndRgn.CreateRectRgn(0,0, rc.Width(),rc.Height());
    CRgn rgnTemp; 
    // 
    rgnTemp.CreateRectRgn(rc.Width()/32,rc.Height()/32, rc.Width()*31/32,rc.Height()*31/32);
    wndRgn.CombineRgn(&wndRgn, &rgnTemp, RGN_DIFF);
    rgnTemp.DeleteObject();
    //
    SetWindowRgn(wndRgn,TRUE);//!!!
    wndRgn.DeleteObject();
    }
    为了明显把背景改为红的。
    BOOL CBaoView::OnEraseBkgnd(CDC* pDC) 
    {
    // TODO: Add your message handler code here and/or call default
        CRect rect;
        GetClientRect(rect);
        pDC->FillSolidRect(rect, RGB(255,0,0));
    return TRUE;
    // return CFormView::OnEraseBkgnd(pDC);
    }
      

  12.   

    不好意思,今天上了一天课,现在才上网。
    哥,我建了3个工程,试了你给的代码,没效果啊!没法挖空哦!
    而且我觉得把挖空代码写在OnInitialUpdate不合适。因为OnInitialUpdate主要是初始化视图中的控件的,这时候都已经把View建立完成了。
      

  13.   

    OnInitialUpdate主要是初始化视图,你的formview相当dlg。
    你创建一个sdi;formview把我的代码放进去,没问题的。
      

  14.   

    哥,工程在http://dl.dbank.com/c0epl76hyx里,你有空就帮我看看嘛。
    VS2010
      

  15.   

    你应该把CreateRect放在OnWndMsg的WM_SIZE里面
      

  16.   

    少改了一下,可以改变大小。// baoView.cpp : implementation of the CBaoView class
    //#include "stdafx.h"
    #include "bao.h"#include "baoDoc.h"
    #include "baoView.h"#ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif/////////////////////////////////////////////////////////////////////////////
    // CBaoViewIMPLEMENT_DYNCREATE(CBaoView, CFormView)BEGIN_MESSAGE_MAP(CBaoView, CFormView)
    //{{AFX_MSG_MAP(CBaoView)
    ON_WM_ERASEBKGND()
    ON_WM_SIZE()
    //}}AFX_MSG_MAP
    // Standard printing commands
    ON_COMMAND(ID_FILE_PRINT, CFormView::OnFilePrint)
    ON_COMMAND(ID_FILE_PRINT_DIRECT, CFormView::OnFilePrint)
    ON_COMMAND(ID_FILE_PRINT_PREVIEW, CFormView::OnFilePrintPreview)
    END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////
    // CBaoView construction/destructionCBaoView::CBaoView()
    : CFormView(CBaoView::IDD)
    {
    //{{AFX_DATA_INIT(CBaoView)
    // NOTE: the ClassWizard will add member initialization here
    //}}AFX_DATA_INIT
    // TODO: add construction code here}CBaoView::~CBaoView()
    {
    }void CBaoView::DoDataExchange(CDataExchange* pDX)
    {
    CFormView::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(CBaoView)
    // NOTE: the ClassWizard will add DDX and DDV calls here
    //}}AFX_DATA_MAP
    }BOOL CBaoView::PreCreateWindow(CREATESTRUCT& cs)
    {
    // TODO: Modify the Window class or styles here by modifying
    //  the CREATESTRUCT cs
    cs.style &= ~ (WS_VSCROLL | WS_HSCROLL); return CFormView::PreCreateWindow(cs);
    }
    #define A_BIT_MORE 4
    void CBaoView::OnInitialUpdate()
    {
    CFormView::OnInitialUpdate();
    GetParentFrame()->RecalcLayout();
    ResizeParentToFit();
    //镂空
    m_bWhite=FALSE;
    CRect rc;
    GetClientRect(&rc); CRgn wndRgn;
    wndRgn.CreateRectRgn(0,0, rc.Width()+A_BIT_MORE,rc.Height()+A_BIT_MORE);
    CRgn rgnTemp; 
    // variable
    // rgnTemp.CreateRectRgn(rc.Width()/32,rc.Height()/32, (rc.Width()*31)/32,(rc.Height()*31)/32);
    // fixed
    rgnTemp.CreateRectRgn(6+2,6+2, rc.Width()-6,rc.Height()-6);
    wndRgn.CombineRgn(&wndRgn, &rgnTemp, RGN_DIFF);
    rgnTemp.DeleteObject();
    //
    SetWindowRgn(wndRgn,TRUE);//!!!
    wndRgn.DeleteObject();
    }
    /////////////////////////////////////////////////////////////////////////////
    // CBaoView printingBOOL CBaoView::OnPreparePrinting(CPrintInfo* pInfo)
    {
    // default preparation
    return DoPreparePrinting(pInfo);
    }void CBaoView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
    {
    // TODO: add extra initialization before printing
    }void CBaoView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
    {
    // TODO: add cleanup after printing
    }void CBaoView::OnPrint(CDC* pDC, CPrintInfo* /*pInfo*/)
    {
    // TODO: add customized printing code here
    }/////////////////////////////////////////////////////////////////////////////
    // CBaoView diagnostics#ifdef _DEBUG
    void CBaoView::AssertValid() const
    {
    CFormView::AssertValid();
    }void CBaoView::Dump(CDumpContext& dc) const
    {
    CFormView::Dump(dc);
    }CBaoDoc* CBaoView::GetDocument() // non-debug version is inline
    {
    ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CBaoDoc)));
    return (CBaoDoc*)m_pDocument;
    }
    #endif //_DEBUG/////////////////////////////////////////////////////////////////////////////
    // CBaoView message handlersBOOL CBaoView::OnEraseBkgnd(CDC* pDC) 
    {
    // TODO: Add your message handler code here and/or call default
        CRect rc;
        GetClientRect(&rc);
    if(m_bWhite)
    pDC->FillSolidRect(rc, RGB(255,255,255));
        else
    pDC->FillSolidRect(rc, RGB(255,0,0));
    return TRUE;
    // return CFormView::OnEraseBkgnd(pDC);
    }void CBaoView::OnSize(UINT nType, int cx, int cy) 
    {
    // CFormView::OnSize(nType, cx, cy);

    // TODO: Add your message handler code here
    //新的镂空
    CRgn nullRgn;
    nullRgn.CreateRectRgn(0,0,cx+A_BIT_MORE,cy+A_BIT_MORE); SetWindowRgn(nullRgn,FALSE);//!!!
    m_bWhite=TRUE;
    RedrawWindow();
    nullRgn.DeleteObject();
    //
    CRgn wndRgn;
    wndRgn.CreateRectRgn(0, 0, cx+A_BIT_MORE, cy+A_BIT_MORE);
    CRgn rgnTemp; 
    // variable
    // rgnTemp.CreateRectRgn(cx/32, cy/32, (cx*31)/32, (cy*31)/32);
    // fixed
    rgnTemp.CreateRectRgn(6+2,6+2, cx-6,cy-6);
    wndRgn.CombineRgn(&wndRgn, &rgnTemp, RGN_DIFF);
    rgnTemp.DeleteObject();
    //
    m_bWhite=FALSE;
    SetWindowRgn(wndRgn,FALSE);//!!!
    wndRgn.DeleteObject();
    RedrawWindow();
    }
      

  17.   

    现在:OnInitialUpdate//镂空
    可以不要
    #define A_BIT_MORE 4
    void CBaoView::OnInitialUpdate()
    {
    CFormView::OnInitialUpdate();
    GetParentFrame()->RecalcLayout();
    ResizeParentToFit();
    return;
    //镂空
      

  18.   

    OnWndMsg的WM_SIZE里面?
    就是添加个视图类的WM_SIZE的消息嘛?
      

  19.   

    重载了OnWndMsg消息后,这里面怎么写啊?
      

  20.   

    给你上传了:
    ‘一个窗口镂空程序(挖洞.zip)’0分
    http://download.csdn.net/detail/schlafenhamster/4296650
    但是VC6的
      

  21.   

    这样你试试
    void CMainFrame::OnSize(UINT nType, int cx, int cy) 
    {
    CFrameWnd::OnSize(nType, cx, cy);

    // TODO: Add your message handler code here

    CRect rc;
      GetWindowRect(&rc);
    CRgn wndRgn;
    wndRgn.CreateRectRgn(0,0, rc.Width(),rc.Height());
    CRgn rgnTemp; 
    rgnTemp.CreateRectRgn(rc.Width()/4, rc.Height()/4, rc.Width()/2,rc.Height()/2);
    wndRgn.CombineRgn(&wndRgn, &rgnTemp, RGN_XOR);
    SetWindowRgn(wndRgn,TRUE);
    rgnTemp.DeleteObject();
    wndRgn.DeleteObject();
    }
      

  22.   

    在Frame中空洞,鼠标会穿透。
      

  23.   

    如果要透明可以这样:
    void CMainFrame::OnSize(UINT nType, int cx, int cy) 
    {
    CFrameWnd::OnSize(nType, cx, cy);

    // TODO: Add your message handler code here
    #ifndef VIEW_CLIP
    CRect rc;
    GetWindowRect(&rc);
    afxDump << rc << " Window\r\n";
    CRgn wndRgn;
    wndRgn.CreateRectRgn(0,0,rc.Width(),rc.Height());
    int offsetY=rc.Height();// 记住frame高度
    //
    CRgn rgnTemp;  
    GetClientRect(&rc);
    afxDump << rc << " Client\r\n";// 0 0  484 304
    rgnTemp.CreateRectRgn(28,28,rc.Width()-20,rc.Height()-20);
    offsetY -= rc.Height();// 求frame与client的差
    rgnTemp.OffsetRgn(0,offsetY-4);// 调整一下
    wndRgn.CombineRgn(&wndRgn, &rgnTemp, RGN_DIFF);
    SetWindowRgn(wndRgn,TRUE);
    rgnTemp.DeleteObject();
    wndRgn.DeleteObject();
    #endif

    }
      

  24.   

    你的代码也能挖空。以前我是把这段代码写在 CMainFrame::OnCreate里的。
    但是还是有一个很蛋疼的问题,就是标题栏变黑了。这个怎么解决呢?
      

  25.   

    vc6上不会有问题。
    你用的‘OR' 搞不好把区域搞不对了。
    你把我的代码用用看。
    注意是’DIFF‘(XOR)
    和:
    rgnTemp.OffsetRgn(0,offsetY-4);//
    这句是下移。 
      

  26.   

    用的就是你的代码哦。
    我觉得应该是,我们CreateRectRgn的区域把MFC自己的建立的窗口给覆盖了,所以才有变黑的原因。
    能不能我们自己建一部分,让MFC框架自己建一部分?
    或者重绘标题栏解决这个?
      

  27.   

    这句就是让开标题和菜单。rgnTemp.OffsetRgn(0,offsetY-4);//
      

  28.   

    如果有toolbar和statusbar还要让开,给你的zip是没有这2个bar的
      

  29.   

    这问题还没解决呢?
    是在不行你用个黑白两色的位图做个rgn算了
      

  30.   

    我的意思是
    CRgn wndRgn;
    wndRgn.CreateRectRgn(0,0,rc.Width(),rc.Height());
    这句就覆盖了标题栏,所以才黑的。
    而这句rgnTemp.OffsetRgn(0,offsetY-4);//
    是挖洞的时候让开了。
      

  31.   

    你重做一个简单的工程。再用我的
    void CMainFrame::OnSize
    试试。
    不会这样的,vc6上没有问题的,4个边都可以拖动,标题不会没有的。
      

  32.   

    哥,我终于找到变黑的原因了!
    原因是我建的工程是:
    VS2010,单文档,基类为CFormView,基于office2007风格的工程。而office2007里面有
    m_wndRibbonBar.Create(this);
    m_wndRibbonBar.LoadFromResource(IDR_RIBBON);这个东东
    我注释上述后,我的标题栏神马的都正常了。你建的工程不是office风格的,所以没出现我说的情况。
    但是m_wndRibbonBar这个东东我程序还是需要,所以问题还是存在。