分享
 
 
 

制作伸展自如、收缩随意的对话框

王朝vc·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

制作伸展自如、收缩随意的对话框

菡冰

Visual C++以其可视化的编程风格成为目前Windows程序设计与开发的主流开发工具。而对话框在Visual C++编程中使用的尤其多。诸如模式对话框、无模式对话框、基于对话框的应用程序等。绝大部分的VC++的书籍中都花费大量的篇幅与笔墨来讲解对话框,这充分证明了对话框在Windows应用程序中的作用。

很多人可能都用过Bitware软件,不知大家还记不记得其界面对话框就可以伸展自如。按下一个按钮,对话框就向水平方向或垂直方向扩展。再按一下按钮,对话框又回复到原来的大小。其实这并不是一个很复杂的问题,下面我们就来讲解如何制作伸展自如的对话框。

1 打开VisualC++工作台,新建工程设为aaa。

2 创建基于对话框的应用程序如下所示:

其余选择皆为缺省即可。

3 在对话框资源中增加控件资源,如下图所示:

其中,最靠右边的一排控件和最靠近下面的两排控件将在对话框伸展或收缩时显示出来或被遮盖。并且为了示例方便,我们有意将他们的值对应起来。并且我们需要通过ClassWizard给每个控件分别关联成员变量,如下所示:

参考DoDataExchange()函数我们就可以知道每个控件所关联的变量了,如下所示:

DDX_Text(pDX, IDC_HEIGHT, m_wHeight);

DDX_Text(pDX, IDC_STREAM_ID, m_wStreamID);

DDX_Text(pDX, IDC_WIDTH, m_wWidth);

DDX_Text(pDX, IDC_SEQUENCE_ORDER, m_wSequenceOrder);

DDX_Text(pDX, IDC_MAX_RATE, m_dwMaxRate);

DDX_Text(pDX, IDC_MIN_RATE, m_dwMinRate);

DDX_Text(pDX, IDC_HEIGHT2, m_wHeight2);

DDX_Text(pDX, IDC_MAX_RATE2, m_dwMaxRate2);

DDX_Text(pDX, IDC_MIN_RATE2, m_dwMinRate2);

DDX_Text(pDX, IDC_SEQUENCE_ORDER2, m_wSequenceOrder2);

DDX_Text(pDX, IDC_STREAM_ID2, m_wStreamID2);

DDX_Text(pDX, IDC_WIDTH2, m_wWidth2);

DDX_Check(pDX, IDC_HORIZONTAL, m_bHorizontal);

DDX_Check(pDX, IDC_VERTICAL, m_bVertical);

实际上,我们也可以不用ClassWizard而直接将上面的一段代码copy到DoDataExchange()函数的

//{{AFX_DATA_MAP(CAaaDlg)

......

//}}AFX_DATA_MAP

之间,(注意一定要在“//{{AFX_DATA_MAP(CAaaDlg)”与“//}}AFX_DATA_MAP”之间)。

同时在aaaDlg.h文件中,在

//{{AFX_DATA(CAaaDlg)

enum { IDD = IDD_AAA_DIALOG };

......

//}}AFX_DATA

之间增加如下变量定义即可:

(注意一定要在“//{{AFX_DATA(CAaaDlg)”与“//}}AFX_DATA”之间)

UINT m_wHeight;

UINT m_wStreamID;

UINT m_wWidth;

UINT m_wSequenceOrder;

DWORD m_dwMaxRate;

DWORD m_dwMinRate;

UINT m_wHeight2;

DWORD m_dwMaxRate2;

DWORD m_dwMinRate2;

UINT m_wSequenceOrder2;

UINT m_wStreamID2;

UINT m_wWidth2;

BOOL m_bHorizontal;

BOOL m_bVertical;

5 在完成上面的步骤后,我们就可以定义几个新的变量用来保存窗口伸展状态时的信息以及收缩状态时的信息。如下:

WORD m_wOrigrinWidth; //原始状态下的窗口宽度

WORD m_wReducedWidth; //收缩状态下的窗口宽度

WORD m_wOrigrinHeight; //原始状态下的窗口高度

WORD m_wReducedHeight; //收缩状态下的窗口高度

WORD m_screenWidth; //屏幕宽度

WORD m_screenHeight; //屏幕高度

在完成以上所有的步骤后,就可以对窗口的伸展与收缩进行随心所欲的控制了,首先我们来侃侃具体的代码,下面再进行具体的解释。代码为:

CenterWindow(NULL);

m_screenWidth = GetSystemMetrics(SM_CXSCREEN);

m_screenHeight = GetSystemMetrics(SM_CYSCREEN);

WINDOWPLACEMENT* lpwndpl=new WINDOWPLACEMENT;

GetWindowPlacement(lpwndpl);

m_wOrigrinWidth = lpwndpl->rcNormalPosition.right;

m_wOrigrinWidth -= lpwndpl->rcNormalPosition.left;

m_wOrigrinHeight = lpwndpl->rcNormalPosition.bottom;

m_wOrigrinHeight -= lpwndpl->rcNormalPosition.top;

LPRECT lpRect1,lpRect2;

lpRect1=new RECT;

lpRect2=new RECT;

GetDlgItem(IDC_PROGRESS_BAR)->GetWindowRect(lpRect1);

GetDlgItem(IDC_STREAM_ID)->GetWindowRect(lpRect2);

lpwndpl->rcNormalPosition.right=(lpRect1->right+lpRect2->left)/2;

m_wReducedWidth = lpwndpl->rcNormalPosition.right;

m_wReducedWidth -= lpwndpl->rcNormalPosition.left;

GetDlgItem(IDC_PROGRESS_BAR)->GetWindowRect(lpRect1);

GetDlgItem(IDC_SEQUENCE_ORDER2)->GetWindowRect(lpRect2);

lpwndpl->rcNormalPosition.bottom=(lpRect1->bottom+lpRect2->top)/2;

m_wReducedHeight = lpwndpl->rcNormalPosition.bottom;

m_wReducedHeight -= lpwndpl->rcNormalPosition.top;

delete lpRect1;

delete lpRect2;

if(m_bHorizontal == TRUE)

{

lpwndpl->rcNormalPosition.right = lpwndpl->rcNormalPosition.left;

lpwndpl->rcNormalPosition.right += m_wOrigrinWidth;

lpwndpl->rcNormalPosition.bottom = lpwndpl->rcNormalPosition.top;

lpwndpl->rcNormalPosition.bottom += m_wReducedHeight;

}

else

{

lpwndpl->rcNormalPosition.right = lpwndpl->rcNormalPosition.left;

lpwndpl->rcNormalPosition.right += m_wReducedWidth;

lpwndpl->rcNormalPosition.bottom = lpwndpl->rcNormalPosition.top;

lpwndpl->rcNormalPosition.bottom += m_wReducedHeight;

}

if(m_bVertical == TRUE)

{

lpwndpl->rcNormalPosition.right = lpwndpl->rcNormalPosition.left;

lpwndpl->rcNormalPosition.right += m_wReducedWidth;

lpwndpl->rcNormalPosition.bottom = lpwndpl->rcNormalPosition.top;

lpwndpl->rcNormalPosition.bottom += m_wOrigrinHeight;

}

else

{

lpwndpl->rcNormalPosition.right = lpwndpl->rcNormalPosition.left;

lpwndpl->rcNormalPosition.right += m_wReducedWidth;

lpwndpl->rcNormalPosition.bottom = lpwndpl->rcNormalPosition.top;

lpwndpl->rcNormalPosition.bottom += m_wReducedHeight;

}

SetWindowPlacement(lpwndpl);

上面这段代码首先将窗口置于屏幕中间,这可以通过函数CenterWindow(GetDesktopWindow()) 来实现,函数 CenterWindow()的用法为:

void CenterWindow( CWnd* pAlternateOwner = NULL );

其中参数pAlternateOwner指向所想居中的窗口的指针。

然后利用函数GetSystemMetrics( int nIndex )得到系统当前设置如屏幕分辨率等。

nIndexs= SM_CXSCREEN 时函数返回屏幕的宽度;返回值单位为像素点。

nIndexs= SM_CYSCREEN 时函数返回屏幕的高度;返回值单位为像素点。

函数BOOL GetWindowPlacement( WINDOWPLACEMENT* lpwndpl ) 是最重要的。他的参数为一个指向结构变量WINDOWPLACEMENT的指针(lpwndpl);其中WINDOWPLACEMENT结构变量数据结构具体为:

typedef struct tagWINDOWPLACEMENT { /* wndpl */

UINT length;

UINT flags;

UINT showCmd;

POINT ptMinPosition;

POINT ptMaxPosition;

RECT rcNormalPosition;

} WINDOWPLACEMENT;

他包含了窗口在屏幕上的定位信息。其中成员变量的含义为:

length:指结构变量的长度,单位字节。

flags: 标志值,控制窗口最小化或窗口还原的方法,可以取如下值:

WPF_SETMINPOSITION:指定窗口最小化时的x位置和y位置。

WPF_RESTORETOMAXIMIZED:指定窗口以最大化方式还原,尽管可能窗口并不是在最大化时最小化的。不改变窗口的缺省还原方式。

showCmd:指定窗口的当前显示状态。可以取值:

SW_HIDE:隐藏窗口并激活另一窗口。

SW_MINIMIZE:最小化指定窗口并激活系统窗口列表中最顶层窗口。

SW_RESTORE:激活并显示窗口,如果窗口处于最小化或最大化状态,则窗口还原到原始大小和位置。

SW_SHOW:以窗口的当前大小和位置激活并显示窗口。

SW_SHOWMAXIMIZED:以最大化方式激活并显示窗口。

SW_SHOWMINIMIZED:以图标方式激活并显示窗口。

SW_SHOWMINNOACTIVE:以图标方式窗口。 但不改变窗口的活动状态。

SW_SHOWNA:以窗口的当前状态显示窗口。

SW_SHOWNOACTIVATE:以窗口最近一次的大小和位置显示窗口。 但不改变窗口的活 动状态。

SW_SHOWNORMAL:激活并显示窗口。如果窗口被最大化或最小化,则窗口还原到原始大小和位置。

ptMinPosition:指定窗口最小化时的左伤角坐标。

ptMaxPosition:指定窗口最大化时的左伤角坐标。

rcNormalPosition:指定窗口在还原时的坐标。

通过灵活使用函数GetWindowPlacement()就可以得到窗口的配置信息。

看到这,可能有些读者已经想到了GetWindowPlacement()函数的姐妹函数SetWindowPlacement(),不用多说,其用法如下:

BOOL SetWindowPlacement( WINDOWPLACEMENT* lpwndpl );

显然,通过函数SetWindowPlacement(),再加以简单的计算,我们就可以来设置窗口的位置、大小以及状态等,从而可以自如地控制窗口显示与否以及窗口的大小、位置等。这里我们就不再多解释了。

6 利用ClassWizard对控件IDC_HORIZONTAL和IDC_VERTICAL增加消息映射BB_CLICKED,

并分别在消息映射函数中增加如下代码如下:

void CAaaDlg::OnHorizontal()

{

// TODO: Add your control notification handler code here

m_bHorizontal = !m_bHorizontal;

UpdateData(FALSE);

WINDOWPLACEMENT* lpwndpl=new WINDOWPLACEMENT;

GetWindowPlacement(lpwndpl);

if(m_bHorizontal == TRUE)

{

lpwndpl->rcNormalPosition.right = lpwndpl->rcNormalPosition.left;

lpwndpl->rcNormalPosition.right += m_wOrigrinWidth;

/*

lpwndpl->rcNormalPosition.bottom = lpwndpl->rcNormalPosition.top;

lpwndpl->rcNormalPosition.bottom += m_wReducedHeight;

*/

}

else

{

lpwndpl->rcNormalPosition.right = lpwndpl->rcNormalPosition.left;

lpwndpl->rcNormalPosition.right += m_wReducedWidth;

/*

lpwndpl->rcNormalPosition.bottom = lpwndpl->rcNormalPosition.top;

lpwndpl->rcNormalPosition.bottom += m_wReducedHeight;

*/

}

SetWindowPlacement(lpwndpl);

delete lpwndpl;

}

void CAaaDlg::OnVertical()

{

// TODO: Add your control notification handler code here

m_bVertical = !m_bVertical;

UpdateData(FALSE);

WINDOWPLACEMENT* lpwndpl=new WINDOWPLACEMENT;

GetWindowPlacement(lpwndpl);

if(m_bVertical == TRUE)

{

lpwndpl->rcNormalPosition.bottom = lpwndpl->rcNormalPosition.top;

lpwndpl->rcNormalPosition.bottom += m_wOrigrinHeight;

}

else

{

lpwndpl->rcNormalPosition.bottom = lpwndpl->rcNormalPosition.top;

lpwndpl->rcNormalPosition.bottom += m_wReducedHeight;

}

SetWindowPlacement(lpwndpl);

delete lpwndpl;

}

7 最后利用ClassWizard对控件IDC_BEGIN_SIMULATE增加消息映射BB_CLICKED。在这里我们模拟了一个100次循环的随机数显示程序。具体大妈如下:

void CAaaDlg::OnBeginSimulate()

{

// TODO: Add your control notification handler code here

srand((unsigned)time(NULL));

char temp[10];

SetDlgItemText(IDC_STATIC11,"Now Beginning ...");

for(int i=0;i<m_maxRange;i++)

{

m_pProgressCtrl->SetPos(i);

m_wSequenceOrder = m_wSequenceOrder2 = i;

m_wStreamID = m_wStreamID2 = rand();

m_wHeight = m_wHeight2 = rand();

m_wWidth = m_wWidth2 = rand();

m_dwMaxRate = m_dwMaxRate2 = rand();

m_dwMinRate = m_dwMinRate2 = rand();

switch(i%4)

{

case 0:

sprintf(temp,"欢 迎 使 用");

break;

case 1:

sprintf(temp,"迎 使 用 欢");

break;

case 2:

sprintf(temp,"使 用 欢 迎");

break;

case 3:

sprintf(temp,"用 欢 迎 使");

break;

}

SetDlgItemText(IDC_WELCOME,temp);

UpdateData(FALSE);

UpdateWindow();

Sleep(50);

}

SetDlgItemText(IDC_WELCOME,"欢 迎 使 用");

SetDlgItemText(IDC_STATIC11,"Now Finnished ...");

}

8 完成以上所有的步骤之后,我们就可以编译程序并运行。运行结果如下:

(a) (b)

(a): 程序启动时对话框状态

(b): 点击Horizontal框后对话框状态。

(c) (d)

(c): 点击Vertical框后对话框状态。

(d): 点击BeginSimulating按钮后系统模拟运行对话框状态。

在本程序中,我们还用到了一些其它的技巧如修改窗口标题,进程状态条的显示、动态字符串显示以及不通过ClassWizard而直接通过在.cpp和.h文件中增加代码的方法来关联控件与成员变量和消息映射等,这些都是一些很实用的技巧,读者可以参考上面的代码以及源程序细细体会,这里我们就不多说了。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有