子类化的控件用Create动态创建时无法获得rect?

hio131 2012-01-22 11:57:15
如下代码

CString szCaption(_T("Button"));
CRect rct;
m_btnOK.GetWindowRect(&rct);//用OK按钮的Rect测试
DWORD dwStyle = m_btnOK.GetStyle();
CXButton btn;//CXButton是自定义按钮类
btn.Create((LPCTSTR)szCaption,dwStyle,rct,this,10001);
btn.ShowWindow(SW_SHOW);

然后在CXButton中

void CXButton::PreSubclassWindow()
{
CRect rct;
this->GetWindowRect(rct);//区域是空的
CString szCaption;
this->GetWindowText(szCaption);//空字串
DWORD dwStyle = this->GetStyle();//可以正确获得
CString szTemp;
szTemp.Format(_T("Caption:%s\tRect:top=%dleft=%dbottom=%dright=%d\tStyle:%d"),szCaption,rct.top,rct.left,rct.bottom,rct.right,dwStyle);
::MessageBox(NULL,szTemp,_T("E"),MB_OK);//这里有个断言通不过 AfxMessageBox也一样
}

我测试了BUTTON和EDIT 一样这个情况,而且这个问题只在动态创建控件时出现,如果定义为成员,上述代码都能正确获得信息……求解这是怎么回事?
...全文
163 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
schlafenhamster 2012-01-25
  • 打赏
  • 举报
回复
因为你用的VS5,我是VC6。不过我想不会差这么多。你不能传代码。就帮不了你了。
hio131 2012-01-24
  • 打赏
  • 举报
回复
我用的VS05

调试了一下 静态按钮不是用CWnd::Create来创建的,而是由MFC自己调用了API,CWnd::Create的处理流程似乎不太一样

而且我试了,在presubclasswindow中,动态创建的按钮无法正确获得父窗口,用GetParent得到的窗口类,句柄是查不到的(SPY++)不知道为什么。
-----------------------------------------------
CRgn r;
r.CreateRectRgn(/*355*/30,30,1000,1000);//(屏幕坐标)对话框左103,按钮左222,再偏移30 是355
SetWindowRgn(r, TRUE);

我用这三行代码测试,动态创建的按钮CreateRectRgn坐标是屏幕坐标,静态按钮用的是按钮的窗口坐标

似乎跟映射模式之类的有关系……? 我实在有些搞不懂了

现在我先判断按钮是动态创建的还是静态创建的,如果动态的就从Create中获得Rect 勉强也达到了效果 不过这个问题到底是没解决啊
schlafenhamster 2012-01-24
  • 打赏
  • 举报
回复
在“DrawItem里无法获得正确的rect和caption”不会有问题吧?这时窗口已产生。
是没有还是不正确?
schlafenhamster 2012-01-24
  • 打赏
  • 举报
回复
给你的代码在VC6上是完全正确的。
要是可以把你的代码上传到你的资源,大家看看。
hio131 2012-01-24
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 schlafenhamster 的回复:]

哪你就复制一下吧,代码是对的。
[/Quote]


- - 光复制是没用的

代码就摆在那 GetWindowText就是拿不到 我有什么办法? 我实在搞不懂才来问的
schlafenhamster 2012-01-24
  • 打赏
  • 举报
回复
哪你就复制一下吧,代码是对的。
hio131 2012-01-24
  • 打赏
  • 举报
回复
我晕 看来你没看清楚

这个CXButton是我自己准备写的 - - 不是CXPButton
schlafenhamster 2012-01-24
  • 打赏
  • 举报
回复
CXPButton里不是有代码吗?
void CXPButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
// TODO: Add your code to draw the specified item

CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
CRect rect = lpDrawItemStruct->rcItem;
UINT state = lpDrawItemStruct->itemState;
CPoint pt;
CString strText;
CString &m_title = strText;
GetWindowText(strText);
。。。
hio131 2012-01-24
  • 打赏
  • 举报
回复
我觉得问题说的挺清楚的了啊…………


没办法了 求代码吧…… 只要动态创建出来的按钮能在presubclasswindow和drawitem中获得正确的信息就好
hio131 2012-01-23
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 schlafenhamster 的回复:]

按你的目的,可以放:
void CXButton::OnSize(UINT nType, int cx, int cy)
[/Quote]

这只是测试 我是在自绘时发现的 在DrawItem里无法获得正确的rect和caption,后来发现在presubclasswindow里也不行
schlafenhamster 2012-01-23
  • 打赏
  • 举报
回复
"而且这个问题只在动态创建控件时出现,如果定义为成员,上述代码都能正确获得信息"
因为定义为成员时,初始化(Create)已由windows完成。
schlafenhamster 2012-01-23
  • 打赏
  • 举报
回复
按你的目的,可以放:
void CXButton::OnSize(UINT nType, int cx, int cy)
hio131 2012-01-23
  • 打赏
  • 举报
回复

再补充一下

void CXButton::PreSubclassWindow()
{
CButton::PreSubclassWindow();
CRect rct;
this->GetWindowRect(rct);//空
CString szCaption;
this->GetWindowText(szCaption);//空
DWORD dwStyle = this->GetStyle();//传入的dwStyle
CString szTemp;
szTemp.Format(_T("Caption:%s\tRect:top=%dleft=%dbottom=%dright=%d\tStyle:%d"),szCaption,rct.top,rct.left,rct.bottom,rct.right,dwStyle);
::MessageBox(NULL,szTemp,_T("E"),MB_OK);//应用程序异常,调试会发现是一个断言,AfxMessageBox一样
}
hio131 2012-01-23
  • 打赏
  • 举报
回复
现在的问题是


//TDlg.h

class CTDlg : public CDialog
{
//...
CButton m_Btn1;//DDX绑定,正常
CXButton m_Btn2;//DDX绑定,CXButton成员函数中可正常获得rect和WindowText
CButton *m_pBtn3;//动态生成,正常
CXButton *m_pBtn4;//动态生成,异常
BOOL bIsCreated;//构造函数中被初始化为FALSE
//...
}

//TDlg.cpp
void CTDlg::OnBnClickedOk()
{
if (bIsCreated == FALSE)
{
CString szCaption(_T("Button"));
CRect rct(0,0,60,60);
DWORD dwStyle = m_btnOK.GetStyle();
m_pBtn3 = new CButton;
m_pBtn3->Create((LPCTSTR)szCaption,dwStyle,rct,this,100001);
//m_pBtn3的动态创建,正常,换成m_pBtn4,在CXButton的成员函数中无法获得rect和WindowText
m_pBtn3->ShowWindow(SW_SHOW);
bIsCreated = TRUE;
return;
}
m_pBtn3->MoveWindow(0,0,100,100);//正常,pBtn3所指对象没被销毁
return;
}
hio131 2012-01-23
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 schlafenhamster 的回复:]

你问的是“void CXButton::PreSubclassWindow()”
有没有从CButton 直接继承一个 类试试 ?
估计同样不行。
[/Quote]

CXButton是从CButton继承来的啊
hio131 2012-01-23
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 solio5 的回复:]

你的 btn对象是个局部变量, 函数执行完后当然什么都不剩了,所以也就没显示出来,它只显示了很短暂的一瞬间
[/Quote]

-执行到PreSubclassWindow时Create还没返回

-只要是手动用Create创建的就不行

if (bIsCreated == FALSE)
{

CString szCaption(_T("Button"));
CRect rct;
m_btnOK.GetWindowRect(&rct);
DWORD dwStyle = m_btnOK.GetStyle();
m_pNewBtn = new CButton;//CButton没问题,CXButton在PreSubclassWindow中不能获得rect,也无法自绘
m_pNewBtn->Create((LPCTSTR)szCaption,dwStyle,rct,this,100001);//复制OK按钮的属性
m_pNewBtn->ShowWindow(SW_SHOW);
bIsCreated = TRUE;
return;
}
m_pNewBtn->MoveWindow(0,0,100,100);//无问题
schlafenhamster 2012-01-23
  • 打赏
  • 举报
回复
你问的是“void CXButton::PreSubclassWindow()”
有没有从CButton 直接继承一个 类试试 ?
估计同样不行。
hio131 2012-01-23
  • 打赏
  • 举报
回复
看6楼

第一次执行时create一个按钮,第二次以后只是movewindow 这是可以正常执行的 new出来的对象在函数结束时不会销毁

但同样一段代码 把注释位置的CButton换成CXButton在CXButton内部就无法得到Rect GetWindowText也不行
godsolio 2012-01-22
  • 打赏
  • 举报
回复
你的 btn对象是个局部变量, 函数执行完后当然什么都不剩了,所以也就没显示出来,它只显示了很短暂的一瞬间
wyx100 2012-01-22
  • 打赏
  • 举报
回复
如果new的是CButton程序可以正常运行
加载更多回复(3)

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧