首页

 

发表论文

 
自制软件
 
串口通讯
 
VC/C编程
 
网络通讯
 
机器人控制
 
MATLAB
 
   

cdxCDynamicWnd and derived classes

原作者:by Hans Bühler : codex design

使用评论 comment: 龚建伟 

 

      动态窗口包括对话框、表格视等等,为了忠于原作者,将英文也附上了,本人在做串口调试助手过程中,有些使用的网友反映说有时窗口太小,看数据不方便,于是便找到了这个类,并在网页上得到了其最新的版本,感觉很好,大家需要做动态界面时,不妨用用。这里仅给出了如何使用这个类做对话框,其它功能大家试试,有好作品别忘了给我寄一份。

首先下载类的源程序:下载 (269网罗软件提供链接,包括我做的示例程序)        国外下载

好了,先跟着做一个简单的动态对话框吧,本人是编程菜鸟,总想着人家也不懂,就从最基本做起:

1. 新建项目:在VC6中用MFC新建一个基于对话框的Test项目,并在对话框中加入控件如图1所示,别忘了在Properties中把对话框styles->border的resizable选上,你也可以把Maximize Box选上,等会验证是不是可以放大到全屏;

2.在项目中插入文件:把所有cdx*.cpp和cdx*.h文件copy 到项目文件夹下(多了无所谓),Project->Add to Project->Files中选上cdx*.cpp、cdx*.h和sizeCBar.cpp,sizeCBar.h, Insert; 怎么样,在ClassView中看到了这些类吧。 (cdxCDynamicFormView.cpp cdxCDynamicDialog.cpp cdxCDynamicBar.cpp cdxCDynamicControlsManager.cpp cdxCDynamicPropSheet.cpp cdxCDynamicWnd.cpp cdxCDynamicWndEx.cpp cdxCSizeIconCtrl.cpp,sizeCBar.cpp和它们的头文件,共18个文件全部加入);

3.改变基类:在对话框头文件TestDlg.h中加入 #include "cdxCDynamicDialog.h"; 在对话框实现文件TestDlg.cpp中把"CDialog" 替换成 "cdxCDynamicDialog",注意不要把About对话框的基类CDialog替换了;

        现在你可以试着运行程序,呵,对话框可以改变大小了!但其中控件不行吧,别急,接着来改变对话框中控件的大小;

4.控制控件动态变化方法 对话框中每一个控件(包括静态文本)都必须有一个独立的ID,要注意的是静态文本的ID不能全是IDC_STATIC,可有将它们改变为IDC_STATIC1、IDC_STATIC2等。有两种方法可以使控件动态移动,本人推荐第一种,因为这种方法不用为每一个控件设置控制变量(若控件多,这是一件相当麻烦的事,如我做的串口调试助手

      在我做的示例程序Test中,除编辑控件用了第二种方法,其余控件均用第一种方法

  • 方法一:用DYNAMIC_MAP_ENTRY函数  

      在对话框头文件TestDlg.h : CTestDlg类定义中加入 DECLARE_DYNAMIC_MAP() 一行;再在实现文件TestDlg.cpp中加入:

BEGIN_DYNAMIC_MAP(CTestDlg,cdxCDynamicDialog)
    DYNAMIC_MAP_ENTRY(IDOK, mdRepos, mdRepos)
    DYNAMIC_MAP_ENTRY(IDCANCEL, mdNone, mdRepos)
    DYNAMIC_MAP_ENTRY(IDC_STATIC0, mdNone, mdRepos)
    DYNAMIC_MAP_ENTRY(IDC_STATIC1, mdNone, mdRepos)
    DYNAMIC_MAP_ENTRY(IDC_STATIC2, mdRepos, mdRepos)
    DYNAMIC_MAP_ENTRY(IDC_STATIC3, mdRepos, mdRepos)
    DYNAMIC_MAP_ENTRY(IDC_STATIC4, mdRepos, mdRepos)
END_DYNAMIC_MAP()

参数含义:    DYNAMIC_MAP_ENTRY(IDC_STATIC2, mdX, mdY)  其中:mdX控制X方向,mdY控制Y方向
- mdNone (保持不变)
- mdRepos (重新定位:move to left)
- mdResize (按对话框大小相应改变大小 resize)
- mdRelative (保持相应位置,如保持在中间如果变化前其位置在中间的话)

 

  • 方法二: AddSzControl(Hwnd, Mode mdX, Mode mdY); 

        Hwnd为控件的DDX控制变量,利用ClassWizard添加,在示例程序Test中,我为IDC_EDIT1添加了m_ctrlEdit1控制变量,然后在对话框初始化函数OnInitDialog()中添加:

            用AddSzControl(m_ctrlEdit1,mdResize,mdResize);          

5.好了,做好了,你也可以试试了。这个类还可以做出其它界面来,看看类作者提供的示例程序就知道了。

 

 

documentation

1 | Preface, Definition

Definiton:
A dynamic window is a window that automatically repositions its child controls when its size changes.
The opposite behaviour is called static.

The classes described here will help you implementing dynamic dialogs, formviews, property sheets and control bars.

It replaces my former class tree "cdxCSizingDialog, ...".

2 | About this document

Since I found out that not many of you seem to like reading documentation, I shortened this documentation.
If you have any suggestions, problems or questions that are not covered by this text, feel free to write an email to me.

As a result, I won't discuss all my member functions but will give you a quick introduction in making windows dynamic.
The basic example will be a dialog.
The technique is nearly the same for property sheets, formviews and control bars.

Here it is:

small window(picture#1 图1)

We want to make it dynamic i.e. it should look like this if you change its size:

big window
(picture #2)

3 | Techniques

The cdxCDynamicWnd class is a base class of all the ready-to-use classes as cdxCDynamicDialog.
To implement the resizing code, you need to tell the cdxCDynamicWnd object, which of your child controls should react on a resizing of your windows and how.

To do so, there are now two techniques:

  • Using AddSzControl():
    As you may know from my former cdxCSizing... classes, you use one of the AddSzControl() overloads to make the dynamic window known to a child window of it.
    In the upper example window, you would add the following lines to your OnInitDialog() code:

AddSzControl(IDC_BOX_1,mdResize,mdResize);
AddSzControl(IDC_LIST,mdResize,mdResize);
AddSzControl(IDC_EDIT,mdResize,mdRepos);
AddSzControl(IDC_NEW,mdRepos,mdRepos);
AddSzControl(IDOK,mdRelative,mdRepos);
AddSzControl(IDCANCEL,mdRelative,mdRepos);

  • The first argument is the ID of the child control to make known to the dynamic window (note that we do not assign IDC_CHECKBOX since this control does not need to react on changes to the window's size).
  • The second argument defines how the control should be treated if the window's width changes,
    The third defines how to deal with height-changes:
    You can choose among the following constants:
    - mdNone (do nothing)
    - mdRepos (move to left)
    - mdResize (resize)
    - mdRelative (keep relative position; e.g. keep centered if control was centered before)

Among others, the following overloads of AddSzControl() are defined (the wnd parameter might be either an ID or a HWND object while a CWnd casts properly to a HWND):

AddSzControl(wnd, Mode mdX, Mode mdY);
AddSzXControl(wnd, Mode md);
AddSzYControl(hwnd, Mode md);

If you are not satisfied with my predefined modes, you can make your own:
The following overload takes two bytes for each direction: They defined how much percent of the change in width should be added to the left side of the the child control (x1) and to the right side (x2) (equally for height changes):

AddSzControl(wnd, SBYTE x1, SBYTE y1, SBYTE x2, SBYTE y2);
AddSzXControl(wnd, SBYTE x1, SBYTE x2);
AddSzYControl(wnd, SBYTE y1, SBYTE y2);

My predefined modes have the following values:
- mdNone is (x1=0,x2=0)
- mdRepos is (100,100)
- mdResize is (0,100)
- mdRelative is (50,50)

Depending on the base class you use the following functions are suitable places to call AddSzControl():

  • Dialog: OnInitDialog()
  • FormView: OnInitialUpdate()
  • PropPage: OnInitDialog()
  • Using my new dynamic maps:
    Some people noted that it is annoying to use the AddSzControl() method since they don't need OnInitDialog() for example - only for the AddSzControl() code.
    Therefore I added the dynamic maps feature.
    To use it, add the line DECLARE_DYNAMIC_MAP() to your class definition, and add something like:

BEGIN_DYNAMIC_MAP(CTestDlg,cdxCDynamicDialog)
    DYNAMIC_MAP_ENTRY(IDC_BOX_1, mdResize, mdResize)
    DYNAMIC_MAP_ENTRY(IDC_LIST1, mdResize, mdResize)
    DYNAMIC_MAP_ENTRY(IDC_EDIT, mdResize, mdRepos)
    DYNAMIC_MAP_ENTRY(IDC_NEW, mdRepos, mdRepos)
    DYNAMIC_MAP_ENTRY(IDOK, mdRelative, mdRepos)
    DYNAMIC_MAP_ENTRY(IDCANCEL, mdRelative, mdRepos)
END_DYNAMIC_MAP()

If you compare these lines to the above AddSzControl() statements, you'll note that they act similarily.
The following macros are defined:

DYNAMIC_MAP_ENTRY(ID,MODEX,MODEY)
DYNAMIC_MAP_XENTRY(ID,MODEX)
DYNAMIC_MAP_YENTRY(ID,MODEY)

DYNAMIC_MAP_ENTRY_EX(ID,X1,Y1,X2,Y2)
DYNAMIC_MAP_XENTRY_EX(ID,X1,X2)
DYNAMIC_MAP_YENTRY_EX(ID,Y1,Y2)

4 | Example: How to create a dynamic dialog

  1. A dialog:
    I suggest that you used your dialog resource editor to design a dialog as shown in picture #1.
    The names of the controls should indicate their control IDs.
    Important note #1: Every control that should dynamically move need a unique ID (=> it is not possible to move static texts with IDC_STATIC).
    Moreoever, I assume that you have created a dialog class called "CTestDlg" for this dialog.

  2. Resizable border and WS_CLIPCHILDREN for your dialog:
    Please open your dialog's properties (in the resource editor), go to the tab "Styles" and change the "Border" into "resizing" (otherwise use won't be able to resize your dialog although it might be dynamic by code).
    Then, switch to the first tab and activate "clip children".

    NOTE: If "clip children" is on and you use group boxes, these boxes need the WS_EX_TRANSPARENT style (can be found at the "extended styles" tab of the group box).
    This is not a problem with these classes but with the MFC at all !

  3. Changing the base-class of your dialog:
    Open your dialog classes header file, add an
    #include "cdxCDynamicDialog.h"
    to its head and replace all "CDialog" by "cdxCDynamicDialog" in both your header and implementation file.

  4. Define how childs should be moved:
    Since this release, you can choose among the two techniques described above to implement this behaviour (they can be mixed if you need that).

    See above to learn how to do so.

  5. Compile and run.

  6. Open your constructor and try to add  ModifyFlags(flSWPCopyBits,0)  to your code.
    This is an anti-flickering option which does not work with all childconstrols, unfortunately - thus you may need to disable it one time.

Once your code runs, you can modify the behaviour of your class in many ways.

The options you may want to make use of are:

  • Disabling the size icon.
  • Setting a window's minimum and maximum size.
  • Advanced anti-flickering.
  • Advanced AddSzControl() code.
  • Virtual functions that you may like to overload for a more sofisticated dynamic reaction.
  • Default resizing values and many more...

Check the flags, available to you, check functions and if you don't make it work, drop a note to me.

5 | Finally

The classes described in this document have been written by

Hans Bühler, codex design (w)1997 - 2000
hans.buehler@topmail.de

You are free to use and modify the code and the classes but I would like you to note the author (that's me :) in your product's documentation at any place, if possible.
You use this code at your own risk.
Any damange caused by the use or misuse of this code is the sole responsibility of the user.

回到页顶

 

 
   
 

                                             

转载本站原版内容,请注明作者,并说明来自http://www.gjwtech.com