⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch01.htm

📁 好书《C++ Builder高级编程技术》
💻 HTM
📖 第 1 页 / 共 5 页
字号:

  catch(EMCIDeviceError &E)

  {

    AnsiString S("\rUse the File | Open menu item to select an AVI file.");

    
ShowMessage("Bummer: " + E.Message + ". " + S);

  }

}

</FONT></PRE>
<P>As you can see, this code includes a <TT>try..catch</TT> block that shoulders
some exception-handling chores. If you wanted, you could safely leave the 
explicit
<TT>try..catch</TT> block out of this code and the VCL would still automatically
raise an exception if the user has picked the Play option before loading a file.
In that case, the VCL will automatically create an exception that tells the user

No MCI Device Open.</P>
<P>For an error built into a programmer's library, the simple strings popped up by
the VCL are usually very complete and comprehensible error messages. However, you
will probably want to improve on it before showing it to the 
users of one of your
own programs. The code above accomplishes this task by catching the exception, modifying
its output string, and then using custom code to display it for the user.</P>
<P>Exceptions in BCB are exactly like exceptions in normal C++ 
programs, only now
your entire program is automatically wrapped in a <TT>try..catch</TT> block and you
also have a very rich set of exception classes at your disposal courtesy of the VCL.
In particular, you can see that the <TT>Play1Click</TT> method 
catches an exception
class called <TT>EMCIDeviceError</TT>. All VCL exception classes begin with the letter
<TT>E</TT>, so this class might be more readily comprehended as the <TT>MCIDeviceError</TT>
exception class, used to raise exceptions that 
occur when using the <TT>TMediaPlayer</TT>
control.

<DL>
	<DT></DT>
</DL>



<BLOCKQUOTE>
	<P>
<HR>
<FONT COLOR="#000077"><B>NOTE:</B></FONT><B> </B>The <TT>TMediaPlayer</TT> control
	is a wrapper around the now somewhat old-fashioned Windows Media 
Control Interface,
	or MCI--hence the name <TT>MCIDeviceError</TT>. As you will see, BCB can also use
	DirectX, DirectMovie, and other advanced multimedia APIs made by companies such as
	Apple or Intel. In fact, BCB can use any API that works in 
Windows, but this particular
	example happens to use the MCI, which is more than adequate for the task at hand.
	
<HR>


</BLOCKQUOTE>

<P>As will be explained in depth in Chapter 4, &quot;Events,&quot; the following
code gives you access to a 
variable named <TT>E</TT>, of type <TT>EMCIDeviceError</TT>:</P>
<PRE><FONT COLOR="#0066FF">catch(EMCIDeviceError &amp;E)

</FONT></PRE>
<P>As you will see in Chapter 3, you can use <TT>E</TT> to call a number of methods
of the 
<TT>EMCIDeviceError</TT> class. One of these methods is called <TT>Message</TT>,
and it returns a human-readable string that can be displayed to the user. I include
this string in the text I show to the user, but I add other information including
a 
potential response to the error.
<H4><A NAME="Heading30"></A><FONT COLOR="#000077">A Brief Introduction to AnsiStrings</FONT></H4>
<P>One pair of lines that have surely caught your eye by this time are the ones that
use a new, BCB-specific class 
called <TT>AnsiString</TT>:</P>
<PRE><FONT COLOR="#0066FF">AnsiString S(&quot;\rUse the File | Open menu item to select an AVI file.&quot;);

ShowMessage(&quot;Bummer: &quot; + E.Message + &quot;. &quot; + S);

</FONT></PRE>
<P>The <TT>AnsiString</TT> 
class is explained in depth in Chapter 3. For now, all
I will say is that it provides a type of string that is fully compatible with the
Object Pascal strings used by the VCL. In particular, the <TT>AnsiString</TT> class
overrides the + operator to 
support concatenating strings. Underneath it is a simple
string class that most likely calls <TT>strcat</TT> in one of its methods. The use
of operator overloading and several other techniques makes it look and act like a
Pascal string.</P>
<P>Though 
it is tempting to use either plain <TT>NULL</TT>-terminated strings, one
of the string classes from the <TT>STL</TT>, or one from some other library, you
will find that I use <TT>AnsiString</TT>s almost exclusively in the code that accompanies
this 
book. The primary reason for this is their compatibility with the VCL. However,
I am also drawn to their safety and ease of use.
<H4><A NAME="Heading31"></A><FONT COLOR="#000077">Two-Way Tools: Changing Properties
at Runtime</FONT></H4>
<P>The code in 
the <TT>ChangeBackgroundClick</TT> method shows how you can manipulate
properties either in code, or via the Object Inspector:</P>
<PRE><FONT COLOR="#0066FF">void __fastcall TForm1::ChangeBackground1Click(TObject *Sender)

{

  AnsiString 
RootDir(ParamStr(0));

  AnsiString SaveDir = OpenDialog1-&gt;InitialDir;

  AsiString SaveFilter = OpenDialog1-&gt;Filter;

  OpenDialog1-&gt;InitialDir = ExtractFilePath(RootDir);

  OpenDialog1-&gt;Filter = &quot;Picture | *.bmp&quot;;

  if 
(OpenDialog1-&gt;Execute())

  {

    Image1-&gt;Picture-&gt;LoadFromFile(OpenDialog1-&gt;FileName);

    Image1-&gt;Stretch = True;

  }

  OpenDialog1-&gt;InitialDir = SaveDir;

  OpenDialog1-&gt;Filter = SaveFilter;

}

</FONT></PRE>
<P>This code 
changes the <TT>InitialDir</TT> and <TT>Filter</TT> properties of the
<TT>TOpenDialog</TT> object at runtime. At first, you might suspect that the only
way to manipulate a BCB component is through the Object Inspector. However, everything
that you can 
do visually with BCB also can be done in code.</P>
<P>Of course, I could have saved time writing some code here by placing two <TT>TOpenDialog</TT>
controls on the form. However, I do things this way so that

<UL>
	<LI>You can see how BCB's two-way 
tools work. You can do things two ways: You can
	write code, or you can do things visually.
	<P>
	<LI>It is also a potentially more efficient use of memory not to have two copies
	of the object on the form. I would, of course, have to run more tests 
to be sure
	that this technique is really saving memory, but the point is that BCB gives you
	the flexibility to do things as you think best.
</UL>

<P>The <TT>ChangeBackground1Click</TT> method first saves the current state of the
<TT>Filter</TT> and 
<TT>InitialDir</TT> properties. Then it changes them to values
that support the loading of a new bitmap for the background of the form. In particular,
the VCL functions called <TT>ParamStr</TT> and <TT>ExtractFilePath</TT> are used
to get the initial 
name of the program as it was passed to the executable by Windows.
(There is no need to parse <TT>argv</TT>; that task is already done for you by <TT>ParamStr</TT>.)
The <TT>ExtractFilePath</TT> function strips off the executable name, leaving only

the path to the directory where your program was launched. The code then assumes
that some bitmaps suitable for a background are available in that directory, which
is the case with the code that ships with this book.
<H4><A NAME="Heading32"></A><FONT 
COLOR="#000077">The VCL and the Windows API</FONT></H4>
<P>Notice the <TT>LoadFromFile</TT> method used to initialize the <TT>Picture</TT>
property of the <TT>TImage</TT> component:</P>
<PRE><FONT COLOR="#0066FF">  if (OpenDialog1-&gt;Execute())

  {

    
Image1-&gt;Picture-&gt;LoadFromFile(OpenDialog1-&gt;FileName);

    Image1-&gt;Stretch = True;

</FONT></PRE>
<PRE><FONT COLOR="#0066FF"> }

</FONT></PRE>
<P><TT>LoadFromFile</TT> entirely hides the act of loading a bitmap into memory,
getting a 
handle to it, and passing it to the <TT>TImage</TT> component that can
display it to the user.</P>
<P>This capability of components to hide the intricacies of the Windows API from
the user is one of the VCL's key strengths. It would be a mistake, 
however, to view
components as black boxes. They are no more black boxes than in any other object
you would find in OWL, MFC, or any other OOP library. The whole source to the VCL
ships with most versions of BCB and is always available from Borland.


<DL>
	<DT></DT>
</DL>



<BLOCKQUOTE>
	<P>
<HR>
<FONT COLOR="#000077"><B>NOTE:</B></FONT><B> </B>The fact that the VCL is in Pascal
	should not be a great hindrance to most BCB programmers. If you examine the actual
	source files, you will find that 
they consist primarily of calls to the Windows API
	and of calls to other portions of the VCL. Because BCB programmers work with the
	VCL all day, they should have little trouble reading calls to the VCL that happen
	to be wrapped in 
<TT>begin..end</TT> blocks rather than curly braces. Furthermore,
	a Windows API call in Object Pascal looks almost exactly like a Windows API call
	in C++. There is no significant difference in their appearance or performance, as
	long as you are not 
confused by minor differences such as the appearance of a <TT>:=</TT>
	operator where you expect to see a simple <TT>=</TT> operator. In Chapter 2, &quot;Basic
	Facts About C++Builder,&quot; I will show how you can step into the Pascal code of
	the 
VCL with the debugger. 
<HR>


</BLOCKQUOTE>

<P>Even more important than the presence of the source to the VCL is the fact that
you can use BCB to create your own components. If you see yourself as primarily as
a system hacker who wants to be close 
to the Windows API, you can get as close as
you want while creating your own components. In fact, BCB allows you to use the Windows
API at any time, and in any way you want.</P>
<P>Needless to say, good VCL programmers use components whenever 
possible, because
they are so robust. If you need to drop to the Windows API, it is often a good idea
to wrap up the resulting code in a component and then share it with or other programmers--or,
if you prefer, sell it to other programmers.</P>

<P>Tools like Visual Basic or PowerBuilder gave people the mistaken impression that
RAD was innately slow and perhaps designed for programmers who didn't really know
how to write &quot;real&quot; code. Delphi put the lie to that misconception, but
it 
had to struggle uphill against ignorant prejudices concerning Object Pascal. BCB
is not as fully encumbered by that weight as Delphi, and it will show everyone who
cares to listen that the fastest way to build small, tight, robust OOP-based programs

is through RAD.
<H4><A NAME="Heading34"></A><FONT COLOR="#000077">Writing RAW Windows API Code with
BCB</FONT></H4>
<P>Having ended the last section on a rather provocative note, it's perhaps time
to show the more technical side of BCB programming. 
The WinAPICode program shown
below is written entirely using raw Windows API calls. There are no objects in this
program; instead, everything is done in a manner similar to the one Petzold used
back when Windows programming was just getting 
started.</P>
<P>The code shown here does not follow Petzold exactly, in that I use <TT>Windowsx</TT>
and <TT>STRICT</TT> to help make the code more readable, more maintainable, and more
portable. The basic approach, however, is tied very closely to 
the Windows API. For
instance, I have a real <TT>WndProc</TT> and message loop, and I make calls to old
standbys such as <TT>CreateWindow</TT>, <TT>ShowWindow</TT>, <TT>UpdateWindow</TT>,
and <TT>RegisterClass</TT>. The code itself is shown in Listing 
1.3.<BR>
<BR>
<A NAME="Heading35"></A><FONT COLOR="#000077"><B>Listing 1.3. Standard Windows API
program that compiles unchanged in BCB.</B></FONT></P>
<PRE><FONT COLOR="#0066FF">///////////////////////////////////////

// File: WinAPICode.cpp

// 
Project: WinAPICode.cpp

// Copyright (c) 1997 by Charlie Calvert

#define STRICT

#define WIN32_LEAN_AND_MEAN

#include &lt;windows.h&gt;

#include &lt;windowsx.h&gt;

#pragma warning (disable: 4068)

#pragma warning (disable: 4100)

static char 
szAppName[] = &quot;Window1&quot;;

static HWND MainWindow;

LRESULT CALLBACK WndProc(HWND hWindow, UINT Message,

                         WPARAM wParam, LPARAM lParam);

BOOL Register(HINSTANCE hInst);

HWND Create(HINSTANCE hInst, int nCmdShow);


// ===================================

// INITIALIZATION

// ===================================

//////////////////////////////////////

// The WinMain function is the program entry point.

// Register the Window, Create it, enter the Message Loop.


// If either step fails, exit without creating the window

//////////////////////////////////////

#pragma argsused

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance,

                   LPSTR lpszCmdParam, int nCmdShow)

{

  MSG  Msg;

  
if (!hPrevInstance)

    if (!Register(hInst))

      return FALSE;

  MainWindow = Create(hInst, nCmdShow);

  if (!MainWindow)

    return FALSE;

  while (GetMessage(&amp;Msg, NULL, 0, 0))

  {

     TranslateMessage(&amp;Msg);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -