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)绘制了上半部后,我原来的标题栏那些都受到了影响,都变黑了,也覆盖了我标题栏上的一些按钮。我只是想在正中间镂空,不想影响其它地方。
求解
::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)绘制了上半部后,我原来的标题栏那些都受到了影响,都变黑了,也覆盖了我标题栏上的一些按钮。我只是想在正中间镂空,不想影响其它地方。
求解
向大哥如果有时间,可以建个工程试试。
以下是我改进的代码,比较短。放在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();
}
刚刚一直没有仔细看代码
我仔细看了一下你的帖子
问题应该是这样的
通过SetWindowRgn设置的窗体不支持拖拽改变大小
也不支持最大化和还原了
所以一般的处理方式是在OnSize中调用这段设置窗口的代码
而且还有一个问题
你应该设置MainFrame而不是针对子窗口操作
你可以试一下
"你应该设置MainFrame而不是针对子窗口操作"
这是什么意思呢?
你的工程里应该能看到
我把SetWindowRgn((HRGN)WindowRgn.m_hObject/*(HRGN)WindowRgn*/,true);
写在OnSize里是要好些了。
我是用的15楼的代码。就是先画一个完整的大的框,再画一个小的,不需要的框,异或下就可以。
但是由此带来两个问题(原先也有)
1)标题栏变黑了。
2)双击标题栏,边框没了。
要先GetWindowRgn再挖。
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;
可以指定位置。
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);
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);
}
哥,我建了3个工程,试了你给的代码,没效果啊!没法挖空哦!
而且我觉得把挖空代码写在OnInitialUpdate不合适。因为OnInitialUpdate主要是初始化视图中的控件的,这时候都已经把View建立完成了。
你创建一个sdi;formview把我的代码放进去,没问题的。
VS2010
//#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();
}
可以不要
#define A_BIT_MORE 4
void CBaoView::OnInitialUpdate()
{
CFormView::OnInitialUpdate();
GetParentFrame()->RecalcLayout();
ResizeParentToFit();
return;
//镂空
就是添加个视图类的WM_SIZE的消息嘛?
‘一个窗口镂空程序(挖洞.zip)’0分
http://download.csdn.net/detail/schlafenhamster/4296650
但是VC6的
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();
}
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
}
但是还是有一个很蛋疼的问题,就是标题栏变黑了。这个怎么解决呢?
你用的‘OR' 搞不好把区域搞不对了。
你把我的代码用用看。
注意是’DIFF‘(XOR)
和:
rgnTemp.OffsetRgn(0,offsetY-4);//
这句是下移。
我觉得应该是,我们CreateRectRgn的区域把MFC自己的建立的窗口给覆盖了,所以才有变黑的原因。
能不能我们自己建一部分,让MFC框架自己建一部分?
或者重绘标题栏解决这个?
是在不行你用个黑白两色的位图做个rgn算了
CRgn wndRgn;
wndRgn.CreateRectRgn(0,0,rc.Width(),rc.Height());
这句就覆盖了标题栏,所以才黑的。
而这句rgnTemp.OffsetRgn(0,offsetY-4);//
是挖洞的时候让开了。
void CMainFrame::OnSize
试试。
不会这样的,vc6上没有问题的,4个边都可以拖动,标题不会没有的。
原因是我建的工程是:
VS2010,单文档,基类为CFormView,基于office2007风格的工程。而office2007里面有
m_wndRibbonBar.Create(this);
m_wndRibbonBar.LoadFromResource(IDR_RIBBON);这个东东
我注释上述后,我的标题栏神马的都正常了。你建的工程不是office风格的,所以没出现我说的情况。
但是m_wndRibbonBar这个东东我程序还是需要,所以问题还是存在。