?? wtl for mfc programmers, part v.mht
字號:
END_MSG_MAP()
=20
BEGIN_UPDATE_UI_MAP(CMainDlg)
END_UPDATE_UI_MAP()
<SPAN class=3Dcpp-comment>//...</SPAN>
};</PRE>
<P>Notice that <CODE>CMainDlg</CODE> derives from =
<CODE>CUpdateUI</CODE>=20
and has an update UI map. <CODE>OnInitDialog()</CODE> has this =
code, which=20
again should be familiar from the earlier frame window =
examples:</P><PRE> <SPAN class=3Dcpp-comment>// register object for =
message filtering and idle updates</SPAN>
CMessageLoop* pLoop =3D _Module.GetMessageLoop();
ATLASSERT(pLoop !=3D NULL);
pLoop->AddMessageFilter(<SPAN class=3Dcpp-keyword>this</SPAN>);
pLoop->AddIdleHandler(<SPAN class=3Dcpp-keyword>this</SPAN>);
=20
UIAddChildWindowContainer(m_hWnd);</PRE>
<P>This time, instead of <CODE>UIAddToolbar()</CODE> or=20
<CODE>UIAddStatusBar()</CODE>, we call=20
<CODE>UIAddChildWindowContainer()</CODE>. This tells=20
<CODE>CUpdateUI</CODE> that our dialog contains child windows that =
will=20
need updating. If you look at <CODE>OnIdle()</CODE>, you might =
suspect=20
that something is missing:</P><PRE>BOOL CMainDlg::OnIdle()
{
<SPAN class=3Dcpp-keyword>return</SPAN> FALSE;
}</PRE>
<P>You might expect there to be another <CODE>CUpdateUI</CODE> =
method call=20
here to do the actual updating, and you're right, there should be; =
the=20
AppWizard left out a line of code. You need to add this line to=20
<CODE>OnIdle()</CODE>:</P><PRE>BOOL CMainDlg::OnIdle()
{
<B>UIUpdateChildWindows();</B>
<SPAN class=3Dcpp-keyword>return</SPAN> FALSE;
}</PRE>
<P>To demonstrate UI updating, when you click the left-hand bitmap =
button,=20
the right-hand button is enabled or disabled. So first, we add an =
entry to=20
the update UI map, using the flag <CODE>UPDUI_CHILDWINDOW</CODE> =
to=20
indicate that the entry is for a child window:</P><PRE> =
BEGIN_UPDATE_UI_MAP(CMainDlg)
<B>UPDATE_ELEMENT(IDC_ALYSON_BMPBTN, UPDUI_CHILDWINDOW)</B>
END_UPDATE_UI_MAP()</PRE>
<P>Then in the handler for the left button, we call=20
<CODE>UIEnable()</CODE> to toggle the enabled state of the other=20
button:</P><PRE><SPAN class=3Dcpp-keyword>void</SPAN> =
CMainDlg::OnAlysonODBtn ( UINT uCode, <SPAN =
class=3Dcpp-keyword>int</SPAN> nID, HWND hwndCtrl )
{
<SPAN class=3Dcpp-keyword>static</SPAN> <SPAN =
class=3Dcpp-keyword>bool</SPAN> s_bBtnEnabled =3D <SPAN =
class=3Dcpp-keyword>true</SPAN>;
s_bBtnEnabled =3D !s_bBtnEnabled;
UIEnable ( IDC_ALYSON_BMPBTN, s_bBtnEnabled );
}</PRE>
<H2><A name=3Dddv></A>DDV</H2>
<P>WTL's dialog data validation (DDV) support is a bit simpler =
than MFC's.=20
In MFC, you need create separate macros for DDX (to transfer the =
data to=20
variables) and DDV (to validate the data). In WTL, one macro does =
both at=20
the same time. WTL contains basic DDV support using three macros =
in the=20
DDX map:</P>
<DL>
<DT><CODE>DDX_TEXT_LEN</CODE>=20
<DD>Does DDX like <CODE>DDX_TEXT</CODE>, and verifies that the =
string's=20
length (not counting the null terminator) is less than or equal =
to a=20
specified limit.=20
<DT><CODE>DDX_INT_RANGE</CODE> and <CODE>DDX_UINT_RANGE</CODE>=20
<DD>These do DDX like <CODE>DDX_INT</CODE> and =
<CODE>DDX_UINT</CODE>,=20
plus they verify that the number is between a given minimum and =
maximum.=20
<DT><CODE>DDX_FLOAT_RANGE</CODE>=20
<DD>Does DDX like <CODE>DDX_FLOAT</CODE> and verifies that the =
number is=20
between a given minimum and maximum. </DD></DL>
<P>ControlMania2 has an edit box with ID IDC_FAV_SEASON that is =
tied to=20
the member variable <CODE>m_nSeason</CODE>.</P>
<P><IMG height=3D429 alt=3D" [Season selector edit box - 13K] "=20
src=3D"http://www.codeproject.com/wtl/WTL4MFC5/cm2_seasonedit.png" =
width=3D373=20
align=3Dbottom border=3D0></P>
<P>Since the legal values for the season are 1 to 7, the DDV macro =
looks=20
like:</P><PRE> BEGIN_DDX_MAP(CMainDlg)
<SPAN class=3Dcpp-comment>//...</SPAN>
DDX_INT_RANGE(IDC_FAV_SEASON, m_nSeason, <SPAN =
class=3Dcpp-literal>1</SPAN>, <SPAN class=3Dcpp-literal>7</SPAN>)
END_DDX_MAP()</PRE>
<P><CODE>OnOK()</CODE> calls <CODE>DoDataExchange()</CODE> to =
validate the=20
season number. <CODE>m_nSeason</CODE> is filled in as part of the =
work=20
done in <CODE>DoDataExchange()</CODE>.</P>
<H3><A name=3Dddvfail></A>Handling DDV failures</H3>
<P>If a control's data fails validation, =
<CODE>CWinDataExchange</CODE>=20
calls the overridable function <CODE>OnDataValidateError()</CODE>. =
The=20
default implementation just beeps the speaker, so you'll probably =
want to=20
provide a friendlier indication of the error. The prototype of=20
<CODE>OnDataValidateError()</CODE> is:</P><PRE><SPAN =
class=3Dcpp-keyword>void</SPAN> OnDataValidateError ( UINT nCtrlID, BOOL =
bSave, _XData& data );</PRE>
<P><CODE>_XData</CODE> is a struct that =
<CODE>CWinDataExchange</CODE>=20
fills in with details about the data that was entered and the =
allowable=20
range. Here's the definition of the struct:</P><PRE><SPAN =
class=3Dcpp-keyword>struct</SPAN> _XData
{
_XDataType nDataType;
<SPAN class=3Dcpp-keyword>union</SPAN>
{
_XTextData textData;
_XIntData intData;
_XFloatData floatData;
};
};</PRE>
<P><CODE>nDataType</CODE> indicates which of the three members of =
the=20
union is meaningful. Its possible values are:</P><PRE><SPAN =
class=3Dcpp-keyword>enum</SPAN> _XDataType
{
ddxDataNull =3D <SPAN class=3Dcpp-literal>0</SPAN>,
ddxDataText =3D <SPAN class=3Dcpp-literal>1</SPAN>,
ddxDataInt =3D <SPAN class=3Dcpp-literal>2</SPAN>,
ddxDataFloat =3D <SPAN class=3Dcpp-literal>3</SPAN>,
ddxDataDouble =3D <SPAN class=3Dcpp-literal>4</SPAN>
};</PRE>
<P>In our case, <CODE>nDataType</CODE> will be =
<CODE>ddxDataInt</CODE>,=20
which means that the <CODE>_XIntData</CODE> member in =
<CODE>_XData</CODE>=20
is filled in. <CODE>_XIntData</CODE> is a simple =
struct:</P><PRE><SPAN class=3Dcpp-keyword>struct</SPAN> _XIntData
{
<SPAN class=3Dcpp-keyword>long</SPAN> nVal;
<SPAN class=3Dcpp-keyword>long</SPAN> nMin;
<SPAN class=3Dcpp-keyword>long</SPAN> nMax;
};</PRE>
<P>Our <CODE>OnDataValidateError()</CODE> override shows an error =
message=20
telling the user what the allowable range is:</P><PRE><SPAN =
class=3Dcpp-keyword>void</SPAN> CMainDlg::OnDataValidateError ( UINT =
nCtrlID, BOOL bSave, _XData& data )
{
CString sMsg;
=20
sMsg.Format ( _T(<SPAN class=3Dcpp-string>"Enter a number between %d =
and %d"</SPAN>),
data.intData.nMin, data.intData.nMax );
=20
MessageBox ( sMsg, _T(<SPAN =
class=3Dcpp-string>"ControlMania2"</SPAN>), MB_ICONEXCLAMATION );
=20
::SetFocus ( GetDlgItem(nCtrlID) );
}</PRE>
<P>Check out atlddx.h to see the other types of data in an=20
<CODE>_XData</CODE> struct - <CODE>_XTextData</CODE> and=20
<CODE>_XFloatData</CODE>.</P>
<H2><A name=3Dresizing></A>Resizing Dialogs</H2>
<P>One of the first things about WTL that got my attention was its =
built-in support for resizable dialogs. Some time ago, I wrote <A=20
href=3D"http://www.codeproject.com/wtl/wtldlgresize.asp">an =
article on this=20
subject</A>, so please refer to that article for more details. To=20
summarize, you add the <CODE>CDialogResize</CODE> class to the =
dialog's=20
inheritance list, call <CODE>DlgResize_Init()</CODE> in=20
<CODE>OnInitDialog()</CODE>, then chain messages to=20
<CODE>CDialogResize</CODE>.</P>
<H2><A name=3Dupnext></A>Up Next</H2>
<P>In the next article, we'll look at hosting ActiveX controls in =
dialogs,=20
and how to handle events fired by the controls.</P>
<H2><A name=3Dreferences></A>References</H2>
<P><A =
href=3D"http://www.codeproject.com/wtl/wtldlgresize.asp">Using WTL's=20
Built-in Dialog Resizing Class</A> - Michael Dunn</P>
<P><A =
href=3D"http://www.codeproject.com/wtl/propsheetddx.asp">Using DDX and=20
DDV with WTL</A> - Less Wright</P>
<H2><A name=3Drevisionhistory></A>Revision History</H2>
<P>April 28, 2003: Article first published.=20
</P><!-- Article Ends --></DIV>
<H2>About Michael Dunn</H2>
<TABLE width=3D"100%" border=3D0>
<TBODY>
<TR vAlign=3Dtop>
<TD class=3DsmallText noWrap><IMG=20
=
src=3D"http://www.codeproject.com/script/profile/images/{2D6F4A37-6FD0-4C=
EF-AC72-EA9D126E611E}.jpg"><BR><BR><IMG=20
=
src=3D"http://www.codeproject.com/script/images/sitebuild_icon.gif">=20
Site Builder</TD>
<TD class=3DsmallText width=3D"100%">Michael lives in sunny =
Los Angeles,=20
California, and is so spoiled by the weather that he will =
probably=20
never be able to live anywhere else. He started programming =
with an=20
Apple //e in 4th grade, graduated from <A=20
href=3D"http://www.ucla.edu/">UCLA</A> with a math degree in =
1995, and=20
immediately landed a job as a QA engineer at Symantec, =
working on=20
the Norton AntiVirus team. He pretty much taught himself =
Windows and=20
MFC programming, and in 1999 he designed and coded a new =
interface=20
for Norton AntiVirus 2000.<BR><BR>Mike now works as a =
developer at=20
<A href=3D"http://www.napster.com/">Napster</A>, an online=20
subscription music service. He also developed <A=20
href=3D"http://www.ultrabar.com/">UltraBar</A>, an IE =
toolbar plugin=20
that makes web searching easy and trounces the Google =
toolbar; the=20
<A href=3D"http://tinyurl.com/i6sk">CodeProject =
SearchBar</A>; and has=20
co-founded <A =
href=3D"http://www.zabersoft.com/">Zabersoft</A>, a=20
development company with offices in Los Angeles and Odense,=20
Denmark.<BR><BR>He also enjoys his hobbies of playing =
pinball, bike=20
riding, and the occasional PlayStation, Dreamcast, or MAME =
game. He=20
is also sad that he's forgotten the languages he's studied: =
French,=20
Mandarin Chinese, and Japanese.
<P class=3DsmallText>Click <A=20
=
href=3D"http://www.codeproject.com/script/profile/whos_who.asp?vt=3Darts&=
amp;id=3D152">here</A>=20
to view Michael Dunn's online =
profile.</P></TD></TR></TBODY></TABLE><BR>
<H2>Other popular WTL articles:</H2>
<UL>
<LI><A href=3D"http://www.codeproject.com/wtl/wtl4mfc2.asp">WTL =
for MFC=20
Programmers, Part II - WTL GUI Base Classes</A><BR><SPAN=20
class=3Dsmalltext>WTL programming for MFC developers - frame=20
windows</SPAN>
<LI><A =
href=3D"http://www.codeproject.com/wtl/wtldockingwindows.asp">WTL=20
Docking windows</A><BR><SPAN class=3Dsmalltext>This is an =
implementation=20
of docking windows for the WTL library</SPAN>
<LI><A href=3D"http://www.codeproject.com/wtl/wtl4mfc1.asp">WTL =
for MFC=20
Programmers, Part I - ATL GUI Classes</A><BR><SPAN =
class=3Dsmalltext>An=20
introduction to WTL programming for MFC developers</SPAN>
<LI><A href=3D"http://www.codeproject.com/wtl/wtl4mfc4.asp">WTL =
for MFC=20
Programmers, Part IV - Dialogs and Controls</A><BR><SPAN=20
class=3Dsmalltext>Using dialogs and controls in =
WTL</SPAN></LI></UL>
<FORM action=3D/script/rating/code/app/insert_vote.asp =
method=3Dpost><INPUT=20
type=3Dhidden value=3DWTL4MFC5/wtl4/27/2003 name=3Dvote_name> =
<INPUT type=3Dhidden=20
value=3D/wtl/wtl4mfc5.asp name=3Dgoal>=20
<TABLE cellSpacing=3D0 cellPadding=3D1 width=3D"100%" =
bgColor=3D#ff9900=20
border=3D0><TBODY>
<TR>
<TD width=3D"100%">
<TABLE cellSpacing=3D0 cellPadding=3D4 width=3D"100%" =
bgColor=3D#fbedbb=20
border=3D0>
<TBODY>
<TR>
<TD class=3Dsmalltext vAlign=3Dcenter>[<A=20
=
href=3D"http://www.codeproject.com/wtl/wtl4mfc5.asp#__top">Top</A>]</TD>
<TD vAlign=3Dcenter noWrap align=3Dright><I><B>Rate this =
Article=20
for us!</B></I> =
<I>Poor</I><INPUT=20
type=3Dradio value=3D1 name=3Drate><INPUT type=3Dradio =
value=3D2=20
name=3Drate><INPUT type=3Dradio value=3D3 =
name=3Drate><INPUT=20
type=3Dradio value=3D4 name=3Drate><INPUT type=3Dradio =
value=3D5=20
name=3Drate><I>Excellent</I> <INPUT =
class=3DFormButton type=3Dsubmit value=3DVote>=20
=
</TD></TR></TBODY></TABLE></TD></TR
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -