📄 faq7.htm
字号:
<HTML>
<HEAD>
<TITLE>Start a program so it obeys the <TT>nCmdShow</TT> argument (passed by a shortcut)</TITLE>
<META NAME="Author" CONTENT="Harold Howe">
</HEAD>
<BODY BGCOLOR="WHITE">
<CENTER>
<TABLE BORDER=0 CELLPADDING=0 CELLSPACING=0 WIDTH="640">
<TR>
<TD>
<H3>
Start a program so it obeys the <TT>nCmdShow</TT> argument (passed by a shortcut)
</H3>
<P>
<I>This entire FAQ applies only to C++Builder 1.0. Programs written in C++Builder 1.0 would not obey the
<TT>nCmdShow</TT> argument that was passed to <TT>WinMain</TT>. C++Builder 3.0 fixed this problem. If you
use C++Builder 3.0 or newer, this FAQ should be ignored.</I></P>
<P>
This is an extenstion to the
<A HREF="faq5.htm">"Starting a program minimized"</A>
FAQ. The infamous line in SYSTEM.PAS causes VCL programs to
ignore the <TT>nCmdShow</TT> parameter that is passed to the program. One impact of
this is that the user will not be able to choose how to start a program
(minimized, maximized, etc) using shortcuts. Plus, a VCL app that is
started by the registry Run key or by a line in WIN.INI will be passed
an <TT>nCmdShow</TT> value of <TT>SW_SHOWMINNOACTIVATE</TT>. Because the VCL ignores the
<TT>nCmdShow</TT> value, C++Builder programs will not conform to the OS requests. You can
fix this problem by calling an API function to determine the original <TT>nCmdShow</TT> value,
and placing the program in its proper state based on the value.
</P>
<P>
<B>Step 1:</B> Choose View|Project Source from the C++Builder menu so you
can edit the <TT>WinMain</TT> function. Call the API <TT>GetStartupInfo</TT>
function to determine the original nCmdShow value. Then react based on
the value.
</P>
<pre>
WINAPI WinMain<b>(</b>HINSTANCE<b>,</b> HINSTANCE<b>,</b> LPSTR<b>,</b> <b>int</b><b>)</b>
<b>{</b>
<b>int</b> MyCmdShow <b>=</b> SW_SHOWDEFAULT<b>;</b>
STARTUPINFO StartupInfo<b>;</b>
GetStartupInfo<b>(</b><b>&</b>StartupInfo<b>)</b><b>;</b>
<b>if</b><b>(</b>StartupInfo<b>.</b>dwFlags <b>&</b> STARTF_USESHOWWINDOW<b>)</b>
MyCmdShow <b>=</b> StartupInfo<b>.</b>wShowWindow<b>;</b>
<b>try</b>
<b>{</b>
Application<b>-></b>Initialize<b>(</b><b>)</b><b>;</b>
Application<b>-></b>CreateForm<b>(</b><b>__classid</b><b>(</b>TForm1<b>)</b><b>,</b> <b>&</b>Form1<b>)</b><b>;</b>
<b>switch</b><b>(</b>MyCmdShow<b>)</b>
<b>{</b>
<b>case</b> SW_SHOWMINNOACTIVE<b>:</b> <font color="navy">// 7, this is what came from the shortcut</font>
<b>case</b> SW_MINIMIZE<b>:</b> <font color="navy">// 6</font>
<b>case</b> SW_SHOWMINIMIZED<b>:</b> <font color="navy">// 2</font>
Application<b>-></b>ShowMainForm <b>=</b> <b>false</b><b>;</b>
Application<b>-></b>Minimize<b>(</b><b>)</b><b>;</b>
<b>break</b><b>;</b>
<b>case</b> SW_SHOWMAXIMIZED<b>:</b> <font color="navy">// SW_SHOWMAXIMIZED and SW_MAXIMIZE are</font>
<b>case</b> SW_MAXIMIZE<b>:</b> <font color="navy">// same value now. Used to be different</font>
Application<b>-></b>MainForm<b>-></b>WindowState <b>=</b> wsMaximized<b>;</b>
<b>break</b><b>;</b>
<b>case</b> SW_HIDE<b>:</b>
Application<b>-></b>ShowMainForm <b>=</b> <b>false</b><b>;</b>
ShowWindow<b>(</b>Application<b>-></b>Handle<b>,</b> SW_HIDE<b>)</b><b>;</b>
<b>break</b><b>;</b>
<b>default</b><b>:</b>
Application<b>-></b>MainForm<b>-></b>WindowState <b>=</b> wsNormal<b>;</b>
<b>}</b>
Application<b>-></b>Run<b>(</b><b>)</b><b>;</b>
<b>}</b>
<b>catch</b> <b>(</b>Exception <b>&</b>exception<b>)</b>
<b>{</b>
Application<b>-></b>ShowException<b>(</b><b>&</b>exception<b>)</b><b>;</b>
<b>}</b>
<b>return</b> <font color="blue">0</font><b>;</b>
<b>}</b>
</pre>
<P>
<B>Step 2:</B> Setting <TT>ShowMainForm</TT> to <TT>false</TT> has one bad
side effect. The form will not appear when the user restores the program by
clicking on the taskbar icon. You can solve this problem by creating an
<TT>OnRestore</TT> handler for the application. Open the header file for the
main form and add this prototype to your main form's class.
</P>
<PRE>
<B>private:</B> // User declarations
<B>void __fastcall</B> AppRestore(TObject *Sender);
</PRE>
<P>
<B>Step 3:</B> Open the main form's CPP file and code the
<TT>AppRestore</TT> function.
</P>
<PRE>
<B>void __fastcall</B> TForm1::AppRestore(TObject *Sender)
{
Visible = <B>true</B>;
}
</PRE>
<P>
<B>Step 4:</B> Assign the <TT>AppRestore</TT> function to the
<TT>OnRestore</TT> handler of <TT>TApplication</TT>. Make this assignment
in the constructor of the main form.
</P>
<PRE>
<B>__fastcall</B> TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Application->OnRestore = AppRestore;
}
</PRE>
<P>
<B>Final Note:</B> The code works find except for one small glitch. The
taskbar icon for the program should not be selected when the program is
started with <TT>nCmdShow</TT> set to <TT>SW_SHOWMINNOACTIVATE</TT>. The
<TT>TApplication::CreateHandle</TT> function contains code that creates
the taskbar icon, and because of the way Windows works, focuses the
newly created icon. By the time <TT>WinMain</TT> executes, its too late to
respond to <TT>nCmdShow</TT> without activating the icon.
</P>
</TD> </TR>
</TABLE>
</CENTER>
</BODY>
</HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -