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

📄 ch25.htm

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

    Ftp->RemoveDir(S);

    
NewDirClick(NULL);

  }

}



void __fastcall TForm1::CreateDirectory1Click(TObject *Sender)

{

  AnsiString S;

  if (InputQuery("Create Directory", "Directory Name", S))

  {

    Ftp->CreateDirectory(S);

    
NewDirClick(NULL);

  }

}



void __fastcall TForm1::DeleteFile1Click(TObject *Sender)

{

  AnsiString S = ListBox1->Items->Strings[ListBox1->ItemIndex];

  S = *Ftp->CustomToFileName(&S);

  if (MessageBox((HWND)Handle, S.c_str(), 
"DeleteFile?",

      MB_YESNO | MB_ICONQUESTION) == ID_YES)

  {

    Ftp->DeleteFile(S);

    NewDirClick(NULL);

  }

}



void __fastcall TForm1::ListBox1DrawItem(TWinControl *Control, int Index, const 

                                         
Windows::TRect &Rect, TOwnerDrawState State)

{

  ListBox1->Canvas->FillRect(Rect);

  AnsiString S = ListBox1->Items->Strings[Index];

  ListBox1->Canvas->TextOut(Rect.Left, Rect.Top, S);

  char ch = S[1];

  if (ch == `N')

    
ListBox1->Canvas->Draw(Rect.Left, Rect.Top, FFileBitmap);

  else

    ListBox1->Canvas->Draw(Rect.Left, Rect.Top, FFolderBitmap); 

}



void __fastcall TForm1::EditConnectionData1Click(TObject *Sender)

{

  FTPNames->ShowModal(); 

}




void __fastcall TForm1::ListBox1MouseDown(TObject *Sender, TMouseButton Button,

                                         TShiftState Shift, int X, int Y)

{

  if (Shift.Contains(ssRight))

  {

    if (ListBox1->ItemIndex >= 0)

      
ShowMessage(ListBox1->Items->Strings[ListBox1->ItemIndex]);

  }

}



</FONT></PRE>
<P><A NAME="Heading27"></A><FONT COLOR="#000077"><B>Listing 25.5. The header for
the module for picking the next connection from a database.</B></FONT></P>

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

// FTPNames.h

// Project: FTPWININET

// Copyright (c) 1997 by Charlie Calvert

//

#ifndef FtpNames1H

#define FtpNames1H

#include &lt;vcl\Classes.hpp&gt;

#include 
&lt;vcl\Controls.hpp&gt;

#include &lt;vcl\StdCtrls.hpp&gt;

#include &lt;vcl\Forms.hpp&gt;

#include &lt;vcl\DBTables.hpp&gt;

#include &lt;vcl\DB.hpp&gt;

#include &lt;vcl\DBGrids.hpp&gt;

#include &lt;vcl\Grids.hpp&gt;

#include 
&lt;vcl\ExtCtrls.hpp&gt;

#include &lt;vcl\DBCtrls.hpp&gt;

#include &lt;vcl\Buttons.hpp&gt;



class TFTPNames : public TForm

{

__published:

 TTable *FTPTable;

 TDataSource *FTPSource;

 TAutoIncField *FTPTableCode;

 TStringField 
*FTPTableServer;

 TStringField *FTPTableUserID;

 TStringField *FTPTablePassword;

 TDBGrid *DBGrid1;

 TPanel *Panel1;

 TDBNavigator *DBNavigator1;

 TPanel *Panel2;

 TBitBtn *BitBtn1;

 TBitBtn *BitBtn2;

private:

  AnsiString FServer;

  
AnsiString FUserID;

  AnsiString FPassword;

public:

 virtual __fastcall TFTPNames(TComponent* Owner);

 BOOL GetConnectionData(void);

 __property System::AnsiString Server = {read=FServer};

 __property System::AnsiString UserID = {read=FUserID};

 
__property System::AnsiString Password = {read=FPassword};

};



extern TFTPNames *FTPNames;



#endif



</FONT></PRE>
<P><A NAME="Heading28"></A><FONT COLOR="#000077"><B>Listing 25.6. The source for
the module that lets the user pick the next FTP 
connection from a database.</B></FONT></P>
<PRE><FONT COLOR="#0066FF">///////////////////////////////////////

// FTPNames.cpp

// Project: FTPWININET

// Copyright (c) 1997 by Charlie Calvert

//

#include &lt;vcl\vcl.h&gt;

#pragma hdrstop

#include 
&quot;FtpNames1.h&quot;

#pragma resource &quot;*.dfm&quot;

TFTPNames *FTPNames;



__fastcall TFTPNames::TFTPNames(TComponent* Owner): TForm(Owner)

{

}



BOOL TFTPNames::GetConnectionData(void)

{

  if (ShowModal() == mrOk)

  {

    FServer = 
FTPTableServer-&gt;Value;

    FUserID = FTPTableUserID-&gt;Value;

    FPassword = FTPTablePassword-&gt;Value;

    return TRUE;

  }

  else

    return FALSE;

}

</FONT></PRE>
<P>This component is used in the FTPWININET program found on the CD 
that comes with
this book. To use the component, simply drop it on a form and then use the Object
Inspector to fill in the <TT>Server</TT>, <TT>UserID</TT>, and <TT>Password</TT>.</P>
<P>To start a session, simply call the <TT>Connect</TT> method:</P>

<PRE><FONT COLOR="#0066FF">void __fastcall TForm1::ConnectBtnClick(TObject *Sender)

{

  MyFtp1-&gt;Connect();

}

</FONT></PRE>
<P>If you choose not to add the component to the Component Palette, you can create
and initialize the FTP component with 
the following code:</P>
<PRE><FONT COLOR="#0066FF">void __fastcall TForm1::ConnectBtnClick(TObject *Sender)

{

  Ftp = new TMyFtp(this);

  Ftp-&gt;OnNewDir = NewDirClick;

  Ftp-&gt;Server = &quot;devinci&quot;;

  Ftp-&gt;UserID = 
&quot;ccalvert&quot;;

  Ftp-&gt;Password = &quot;flapper&quot;;

  Ftp-&gt;Connect();

  ListBox1-&gt;Items = Ftp-&gt;FindFiles();

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

}

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

void __fastcall 
TForm1::NewDirClick(TObject *Sender)

{

  Caption = FStartCaption + &quot; -&gt;&gt; &quot; + Ftp-&gt;CurDir;

  ListBox1-&gt;Items = Ftp-&gt;FindFiles();

}



</FONT></PRE>
<P>For this code to work, you must <TT>#include</TT> <TT>ftp2.h</TT> at the 
top of
your file, and you must declare the variable <TT>Ftp</TT> as a field of <TT>TForm1:
TMyFtp *Ftp</TT>. You should also add <TT>NewDirClick</TT> to your class declaration
in the header file.</P>
<P>The difference between these two versions of the 
<TT>ConnectBtnClick</TT> method
shows how much simpler using the RAD paradigm is rather than slogging your way through
the old coding techniques. Note in particular the second line in the preceding method;
this line explicitly sets up the event 
handler (closure) for the <TT>OnNewDir</TT>
event.</P>
<P>If you respond to the <TT>OnNewDir</TT> event, you can get a directory listing
for the current FTP site mirrored in a <TT>ListBox</TT> by writing the following
line of code:</P>
<PRE><FONT 
COLOR="#0066FF">void __fastcall TForm1::NewDirClick(TObject *Sender)

{

  Caption = FStartCaption + &quot; -&gt;&gt; &quot; + Ftp-&gt;CurDir;

  ListBox1-&gt;Items = Ftp-&gt;FindFiles();

}

</FONT></PRE>
<P>The first line of code shown here is 
optional; it does nothing more than show
the current directory in the caption of the program. The <TT>FStartCaption</TT> variable
is a field of the <TT>TForm</TT> object that is initialized in the constructor for
the form:</P>
<PRE><FONT 
COLOR="#0066FF">__fastcall TForm1::TForm1(TComponent* Owner)

: TForm(Owner)

{

  FStartCaption = Caption;

}

</FONT></PRE>
<P>The technique of saving the default caption in a global variable for later reuse
is a common one in C++Builder 
programming.</P>
<P>The <TT>FindFile</TT> method called in the <TT>NewDirClick</TT> routine was explained
in the section &quot;After Connecting.&quot;</P>
<P>After you have displayed a directory of files, the program still needs to provide
a technique 
for letting the user change directories. One simple method is to respond
to double-clicks on a directory name by changing into the selected directory.
<H3><A NAME="Heading29"></A><FONT COLOR="#000077">Creating User Draw List Boxes</FONT></H3>
<P>When 
displaying a list of files to the user, you need to provide some clear way
of distinguishing files from directories. One simple way to make this distinction
is with an owner draw list box that provides different icons for the different types
of files 
and directories you want to show the user.</P>
<P>To get started creating an owner draw list box, change the <TT>Style</TT> property
for the list box to <TT>lbOwnerDrawFixed</TT>. This means that you want all the items
in the list box to have the same 
height. You can now associate a graphic item with
the <TT>Object</TT> field of each string in the <TT>TStringList</TT>. Next, you respond
to <TT>OnDrawItem</TT> events.</P>
<P>Here is the constructor for the form, which is used to load the bitmaps to 
be
displayed in the list box from a resource:</P>
<PRE><FONT COLOR="#0066FF">fastcall TForm1::TForm1(TComponent* Owner)

  : TForm(Owner)

{

  FStartCaption = Caption;

  FFolderBitmap = new Graphics::TBitmap;

  FFileBitmap = new Graphics::TBitmap;

  
FFolderBitmap-&gt;Handle = LoadBitmap((HINSTANCE)HInstance, &quot;FolderBmp&quot;);

  FFileBitmap-&gt;Handle = LoadBitmap((HINSTANCE)HInstance, &quot;FileBmp&quot;);

}



</FONT></PRE>
<P>The code shown here explicitly sets the <TT>OnDrawItem</TT> 
event to the <TT>ListBox1DrawItem</TT>
method, but, of course, you could also do this visually, from the Events page of
the Object Inspector. In particular, you could turn to the Events page for the <TT>ListBox1</TT>
control; then you could set the 
<TT>OnDrawItem</TT> event to <TT>ListBox1DrawItem</TT>
or to some other method that you choose. The only requirement, of course, is that
the method be of type <TT>TNotifyEvent</TT>; that is, it must take <TT>TObject Sender</TT>
as its sole 
parameter.</P>
<P>The code goes on to create two bitmaps and then loads the bitmaps from a resource
with the <TT>LoadBitmap</TT> function. <TT>LoadBitmap</TT> is a Windows API routine
that takes the <TT>HInstance</TT> for the program in its first 
parameter and the
name of the resource you want to retrieve in its second parameter. You can then assign
the handle returned by <TT>LoadBitmap</TT> to the handle of the native VCL <TT>TBitmap</TT>
object. After it is assigned to <TT>TBitmap</TT>, you 
no longer have to worry about
disposing the handle, as it will be cleaned up when <TT>TBitmap</TT> is destroyed.
You will, however, have to explicitly destroy the <TT>TBitmap</TT> objects in the
destructor for the form:</P>
<PRE><FONT 
COLOR="#0066FF">__fastcall TForm1::~TForm1()

{

  FFolderBitmap-&gt;Free();

  FFileBitmap-&gt;Free();

}

</FONT></PRE>
<P>The custom RC file called <TT>LISTICON.RC</TT> looks like this:</P>
<PRE><FONT COLOR="#0066FF">FolderBmp BITMAP 
&quot;FOLDER.BMP&quot;

FileBmp BITMAP &quot;FILE.BMP&quot;

</FONT></PRE>
<P>You can include this file in your project by choosing Project | Add to Project
and then browsing for RC files and adding your custom file to the project, as shown
Figure 
25.5. This way, you add the following macro to your project file:</P>
<PRE><FONT COLOR="#0066FF">USERC(&quot;ListIcon.rc&quot;);

</FONT></PRE>
<H6><FONT COLOR="#0066FF"></FONT></H6>
<P><A NAME="Heading30"></A><A HREF="25ebu05.jpg" tppabs="http://pbs.mcp.com/ebooks/0672310228/art/25/25ebu05.jpg">FIGURE 
25.5.</A><FONT COLOR="#000077">
</FONT><I>Adding an RC file to a BCB project.</I></P>
<P><BR>
Remember that you don't want to add this code into the pre-made RES file that C++Builder
makes automatically for your program. Instead, you should create a 
separate RES file,
using the techniques I've described here. The two bitmaps included here are shown
in Figure 25.6.<BR>
<BR>
<A NAME="Heading31"></A><A HREF="25ebu06.jpg" tppabs="http://pbs.mcp.com/ebooks/0672310228/art/25/25ebu06.jpg">FIGURE 25.6.</A><FONT COLOR="#000077">
</FONT><I>The two 16x16 16-color 
folder and file bitmaps used in FTPWININET.</I></P>
<P><BR>
If you don't want to have the C++Builder IDE add the RC file to your project, you
can do so explicitly with only a few seconds' work. Here is how to proceed.</P>
<P>Compile the RC file at the 
command line by passing it as the sole parameter to
the <TT>BRCC32.EXE</TT> utility that ships with C++Builder.</P>
<P>Add the following code at the top of your main form:</P>
<PRE><FONT COLOR="#0066FF">#include &lt;vcl\vcl.h&gt;

#pragma hdrstop


#include &quot;Ftp2.h&quot;

#include &quot;Main.h&quot;

#include &quot;FtpNames1.h&quot;

#pragma resource &quot;*.dfm&quot;

#pragma resource &quot;listicon.res&quot;   // Here is the line you should add to your project!

TForm1 *Form1;

__fastcall 
TForm1::TForm1(TComponent* Owner)

: TForm(Owner)

{

  ... // etc

</FONT></PRE>
<P>The only line that is important here is the seventh, but I have shown you additional
lines from the program so that you can find the context in which to place the 
file.
Both techniques work fine, though the first is probably preferred.</P>
<P>Now that all the resource issues are finally out of the way, you can write the
following code to display the bitmaps in a list box:</P>
<PRE><FONT COLOR="#0066FF">void 
__fastcall TForm1::ListBox1DrawItem(TWinControl *Control, int Index,

  const Windows::TRect &amp;Rect, TOwnerDrawState State)

{

  ListBox1-&gt;Canvas-&gt;FillRect(Rect);

  AnsiString S = ListBox1-&gt;Items-&gt;Strings[Index];

  
ListBox1-&gt;Canvas-&gt;TextOut(Rect.Left, Rect.Top, S);

  char ch = S[1];

  if (ch == `N')

    ListBox1-&gt;Canv

⌨️ 快捷键说明

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