对话框到子控件的切换

类别:VC语言 点击:0 评论:0 推荐:
对话框到子控件的切换 例子:见附件 贴图: 原始界面 被嵌入对话框中的对话框跳出了主窗口 关键字:SetWindowLong,SetWindowPos,SetParent,WS_POPUP,WS_CHILD 背景:准备做一个播放器,底层接口做好了,只需传入一个窗口句柄,就可以在该窗口上面播放媒体了。本来想在一个对话框上放置一个static控件,将static控件句柄传给底层接口就好。普通播放没问题,电影都在static上。但是要求全屏播放,这下就难住了。因为static无法全屏啊。 目的:能将某窗口全屏,但又能将该窗口嵌入另一窗口中。 方案: (1)动态更改static控件的style,并将其父窗口句柄更为NULL,看控件可不可以跳出对话框。此方案实施过,成功。static控件跳出了对话框,成为一个独立的窗口。但是该窗口没法控制,回不去。此方案似乎有问题。由于时间关系,没有深入研究,估计再鼓捣鼓捣说不定能搞出来。 (2)作一个主窗口,上面放一个static,调整其大小到合适位置。再作一个对话框,将该窗口覆盖在static上方,动态更改该对话框,这样就是两个对话框前后重叠,好像是主窗口中的控件了。实施过,成功。但是毛病是控制比较复杂,要算来算去的。后面的主窗口的标题还爱变灰,明眼人一看就知道是两个窗口。不行。 (3)同样是做两个窗口,但是用在播放电影的那个对话框把它当作子控件嵌入到主窗口中,在需要全屏的时候,将其属性更改成窗口,那它就跳出主窗口而全屏了。由于本身是窗口,可以控制它,在需要恢复的时候,再将其嵌入到主窗口中,又成了子控件了。本文就讨论此方案。 步骤: 1, 创建一个以对话框为基础的项目。在对话框中添加一个Static : IDC_FULLSCREEN,拉出适当的大小形状。以容纳另一个窗口。 2, 插入一个对话框资源。去掉上面默认的所有控件。必须修改对话框以下属性: a) Visible TRUE b) Style Child 根据需要修改Title bar。可以自己看看效果。如果有标题栏,则可以在static中移动该窗口。 3, 生成一个新类CMyDlg a) 对该类重载以下两个函数,以免用户敲入回车和Esc键将该窗口关闭。 void OnOK(){return;} void OnCancel(){return;} b) 由于需要与主窗口(也就是其父窗口)通信,在该对话框跳出父窗口后,还需要再次嵌入到父窗口中,所以增加一个父窗口类的实例指针。 CWnd* m_pParent; c) 在CMyDlg的构造函数中,将传递过来的父窗口指针保存起来以备后用: CMyDlg::CMyDlg(CWnd* pParent /*=NULL*/) : CDialog(CMyDlg::IDD, pParent),m_pParent(pParent) { } 4, 有了上面的窗口后,我们不能像普通控件拖到对话框中,所以需要在主窗口类中定义一个指针成员变量保存播放窗口,并动态创建之。 CMyDlg* pDlg; 并在对话框类的构造函数中将其赋值为NULL。在析构中delete pDlg。 5, 在对话框的OnInitDialog函数中初始化CMyDlg;如下: // TODO: 在此添加额外的初始化代码 CWnd* pS = (CWnd*)GetDlgItem(IDC_FULLSCREEN); if (pS ==NULL) { AfxMessageBox("Error"); return FALSE; } if ( pDlg==NULL ) { pDlg = new CMyDlg(pS); pDlg->Create( CMyDlg::IDD,pS ); pDlg->ShowWindow(SW_NORMAL); } 在创建CMyDlg时,将其父窗口指向static窗口。 6, 这时可以运行程序了。当然编译的时候需要添加一些头文件之类的琐碎事情,自己可以搞定。我们可以发现播放窗口在主窗口的static控件中出现了,如果有标题栏,还可以移动。如果播放窗口的边框有resizing的属性,还可以改变大小。玩够了后结束程序,继续。 7, 现在增加将播放窗口跳出主窗口的动作。主要用到的是SetWindowLong函数修改其现有的属性。在一个按钮被按下的事件中处理,主要的功能就是去掉子窗口属性(WS_CHILD)添加弹出窗口属性(WS_POPUP),然后设置其父窗口为NULL。 将代码中注释掉的代码恢复后,就达到全屏的效果了。 void CfullscreenDlg::OnBnClickedButton2() { // TODO: 在此添加控件通知处理程序代码 if ( pDlg == NULL ) return; HWND hWnd = pDlg->GetSafeHwnd(); if ( hWnd == NULL ) return; ::SetWindowLong( hWnd , GWL_STYLE, (::GetWindowLong(hWnd,GWL_STYLE) ) & (~WS_CHILD) & (~WS_DISABLED) | WS_POPUP ); pDlg->SetParent(NULL); //if ( ! ::SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), 0) ) //{ // AfxMessageBox("NO"); //} } 8, 现在运行程序,单击按钮后,我们发现播放窗口真的跳出来了。按下Esc键,退出程序。我们来添加恢复到嵌入主窗口中的功能。 9, 为了简单起见,我们直接在CMyDlg类中实现。给CMyDlg增加一个消息处理函数:鼠标左键弹起,在消息处理中,无非也是修改窗口属性。代码如下: void CMyDlg::OnLButtonUp(UINT nFlags, CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 if ( m_pParent != NULL ) { HWND hWnd = GetSafeHwnd(); if ( hWnd == NULL ) return; LONG newStyle = ::GetWindowLong( hWnd,GWL_STYLE) & (~WS_POPUP) | WS_CHILD | WS_DISABLED ; ::SetWindowLong( hWnd , GWL_STYLE, newStyle) ; SetParent(m_pParent); } CDialog::OnLButtonUp(nFlags, point); } 到此目的达到。

本文地址:http://com.8s8s.com/it/it479.htm