delphi tips and articles 2

1TColor中支持的颜色常量(unit Graphics):
clSystemColor
clScrollBar
clBackground
clActiveCaption
clInactiveCaptio
clMenu
clWindow
clWindowFrame
clMenuText
clWindowText
clCaptionText
clActiveBorder
clInactiveBorder
clAppWorkSpace
clHighlight
clHighlightText
clBtnFace
clBtnShadow
clGrayText
clBtnText
clInactiveCaptionText
clBtnHighlight
cl3DDkShadow
cl3DLight
clInfoText
clInfoBk
clHotLight
clGradientActiveCaption
clGradientInactiveCaption
clMenuHighlight
clMenuBar
clBlack
clMaroon
clGreen
clOlive
clNavy
clPurple
clTeal
clGray
clSilver
clRed
clLime
clYellow
clBlue
clFuchsia
clAqua
clLtGray
clDkGray
clWhite
clMoneyGreen
clSkyBlue
clCream
clMedGray
clNone
clDefault
----------------------------------------------
2 当使用一个数组做参数时,如下表达:
procedure proExt(var var1:array of Integer);
当这个参数是多维的时候,似乎不行,
这时可以如下:
在文件头定义:
TIntegerArray = array of array of Integer;
然后使用TIntegerArray。
procedure proEx1(........)
var
  i:TIntegerArray;
begin
   
end;
procedure proEx2(var2:TIntegerArray);
3在子类的重载的构造函数中调用父类的构造函数
TDescent=class(TForm)
    constructor create(str:string);overload;
end;

constructor create(str:string);
begin
    inherited create(nil);//使用TForm的create(TComponent),相当于java中的super(TComponent);

    //use str here
end;
4获得一个字符串的象素长度
Try TCanvas.TextWidth (see also TextHeight, TextExtent).

5MIDAS

http://www.distribucon.com/papers/midasintro/dl210.htm

http://www.distribucon.com/midas.html

 

6操作xml

http://www.bczs.net/xml/2004/2/6/2708437.xml
http://topic.csdn.net/t/20060220/10/4565317.html

http://maverick.cnblogs.com/archive/2005/01/12/90459.aspx

http://www.graphics.net.cn/document/delphi/002/240.asp

http://homepages.borland.com/ccalvert/TechPapers/Delphi/XMLSimple/XMLSimple.html

XMLTOTree    TreeTOXML:    
http://delphi.about.com/library/weekly/aa101904a.htm


 7打开文件和执行应用程序

http://delphi.about.com/od/windowsshellapi/a/executeprogram.htm,如下:

Executing and Running Applications and Files from Delphi Code

From Zarko Gajic,
Your Guide to Delphi Programming.
FREE Newsletter. Sign Up Now!

How many times have you wanted to execute some program from your Delphi application?

Let's say we have a database application that uses some external backup utility. The back up utility takes parameters from your application, archives data, while your program waits until backup finishes.

On the other hand, have you ever needed to open documents presented in a file listbox, just by double clicking on them, without opening the associated program first?

Finally, imagine a link-label in your program that will take the user to your home page (by executing the Internet Explorer). Moreover, what do you say about sending an e-mail directly from your Delphi application through default Windows e-mail client program (like MS Outlook Express).

ShellExecute

To launch an application or execute a file in Win32 environment we will use the ShellExecute Windows API function. Check out the help on ShellExecute for full description of parameters and error codes returned.
As you will see we can open any type of document from our program without knowing which program is associated with it (this link is defined in the Windows Registry).

Let's see some shell action!
Be sure to add ShellApi to your Unit's uses clause.


Run Notepad

uses ShellApi;
...
ShellExecute(Handle, 'open', 'c:/Windows/notepad.exe', nil, nil, SW_SHOWNORMAL) ;

Open SomeText.txt with Notepad

ShellExecute(Handle,'open', 'c:/windows/notepad.exe','c:/SomeText.txt', nil, SW_SHOWNORMAL) ;

Display the contents of the "DelphiDownload" folder

ShellExecute(Handle,'open', 'c:/DelphiDownload', nil, nil, SW_SHOWNORMAL) ;

Execute a file according to its extension.

ShellExecute(Handle, 'open', 'c:/MyDocuments/Letter.doc',nil,nil,SW_SHOWNORMAL) ;
Here's how to Find an application associated with an extension

Open web site or a *.htm file with the default web explorer

ShellExecute(Handle, 'open', 'http://delphi.about.com',nil,nil, SW_SHOWNORMAL) ;
Here's how to Open a Web Browser in a new window

Send an e-mail with the subject and the message body

var em_subject, em_body, em_mail : string;
begin
  em_subject := 'This is the subject line';
  em_body := 'Message body text goes here';

  em_mail := 'mailto:delphi.guide@about.com?subject=' +
    em_subject + '&body=' + em_body ;

  ShellExecute(Handle,'open',
    PChar(em_mail), nil, nil, SW_SHOWNORMAL) ;
end;
Here's how to send an email with the attachment

Execute a program and wait until it has finished. The following example uses the ShellExecuteEx API function.

// Execute the Windows Calculator and pop up
// a message when the Calc is terminated.
uses ShellApi;
...
var
   SEInfo: TShellExecuteInfo;
   ExitCode: DWORD;
   ExecuteFile, ParamString, StartInString: string;
begin
   ExecuteFile:='c:/Windows/Calc.exe';

   FillChar(SEInfo, SizeOf(SEInfo), 0) ;
   SEInfo.cbSize := SizeOf(TShellExecuteInfo) ;
   with SEInfo do begin
     fMask := SEE_MASK_NOCLOSEPROCESS;
     Wnd := Application.Handle;
     lpFile := PChar(ExecuteFile) ;
{
ParamString can contain the
application parameters.
}
// lpParameters := PChar(ParamString) ;
{
StartInString specifies the
name of the working directory.
If ommited, the current directory is used.
}
// lpDirectory := PChar(StartInString) ;
     nShow := SW_SHOWNORMAL;
   end;
   if ShellExecuteEx(@SEInfo) then begin
     repeat
       Application.ProcessMessages;
       GetExitCodeProcess(SEInfo.hProcess, ExitCode) ;
     until (ExitCode <> STILL_ACTIVE) or
Application.Terminated;
     ShowMessage('Calculator terminated') ;
   end
   else ShowMessage('Error starting Calc!') ;
end;




注意:如果shellexecute出错,将返回<=32的错误码!


8时间的操作
encodedatetime和DecodeDateTime可以将时间在一系列int 1982,9,9,12,12,59,100与datetime型间转换。
用datetimetosqltimestamp(now)可以生成这样结构的record
type TSQLTimeStamp = packed record

    Year : SmallInt;
    Month : Word;
    Day : Word;
    Hour : Word;
    Minute : Word;
    Second : Word;
    Fractions : LongWord;
  end;

formatdatetime('yyyy"-"mm"-"dd',date);

http://delphi.apub.org/doc/2006/07/12/11/10/46/189619.html


9一个dbgrid的问题:


dbgrid.selectedrows有效时,必须使Options property includes dgRowSelect and dgMultiSelect.
10在TTreeview中程序选择一个节点

TTreenode.selected := true;

treeview.selected := node;似乎是错的。

11TQuery.execsql被调用之后,TQuery.active就被设为false了。

12四舍五入的问题

Delphi中使用Round函数得到的答案有时与我们所预期的会不太一样:
采用的是四舍六入五留双。即当舍或入位大于或小于五时按四舍五入来处理,而当舍或入位等于五时,就要看前面一位是什么,根据奇进偶不进,它总是返回一个偶数值。
     示例             结果
i:= Round(11.5)        12
i:= Round(10.5)        10

       这种Round其实是按照银行家算法,统计学上一般都用这种算法,比传统的"四舍五入"要科学。
如果要使用传统的"四舍五入"方法,可以使用下面函数:

http://www.1shang.com/tech/tech2/techList18077.htm

function RoundClassic(R: Real): Int64;
begin
  Result:= Trunc(R);
  if Frac(R) >= 0.5 then
    Result:= Result + 1;
end;

 

http://www.cnblogs.com/abchjb/articles/5668.html

13转载一些技巧

http://www.icwin.net/ShowArtitle.ASP?art_id=5787&cat_id=39

经常有朋友提这样的问题,“我原来在delphi5或者delphi6中用的很熟的控件到哪里去了?是不是在delphi7中没有了呢?这是不是意味着我以前写的代码全都不能够移植到delphi7中来了呢?是不是我必须学习适应这些新的控件呢?”

现在我就对这一问题进行解释,并对在delphi7中的VCL以及CLX进行一下总结,方便有这方面需求的朋友进行查询

其实,我们在原来版本如D5、D6中使用的控件如Quickrep,FastNet等,在D7中仍然是保留的。只是Delphi没有将他们默认的安装到组件面版中来。这些控件包全部保存在Delphi目录的bin下,文件扩展名为.bpl(共将近60个)。
安装这些包的方法很简单,只需点击菜单"component---->Install Packages...",然后使用"ADD"选择需要的包就可以了。


下面就其中的一部分bpl列表说明其中的控件:

dclact70.bpl (Borland Actionbar Components)
包括的控件:TStandardColorMap、TTwilightColorMap、TXPColorMap、TActionToolBar、TActionManager、TActionMainMenuBar、TCustomizeDlg

dclado70.blp(Borland ADO DB Components)
包括的控件:TADOCommand、TADOConnection、TADODataSet、TADOQuery、TADOStoredProc、TADOTable、TRDSConnection

dclbde70.bpl(Borland BDE DB Components)
包括的控件:TDBLookupCombo、TDBLookupList、TBatchMove、TDatabase、TNestedTable、Tquery、TSession、TStoredProc、TTable、TUpdateSQL

dclclxdb70.bpl(Borland CLX Database Components)
包括的控件:TDBCheckBox、TDBComboBox、TDBEdit、TDBImage、TDbListBox、TDBLookupComboBox、TDBLookupListBox、TDBMemo、TDBNavigator、TDBRadioGroup、TDBText、TDBGrid

dclclxstd70.bpl(Borland CLX Standard Components)
包括的控件:TActionList、TBitBtn、TSpeedButton、TCheckListBox、TAnimate、THeaderControl、TIconView、TListView、TPageControl、TProgressBar、TSpinEdit、TStatusBar、TTabControl、TTextBrowser、TTextViewer、TToolBar、TTrackBar、TTreeView、TColorDialog、TFindDialog、TFontDialog、TOpenDialog、TSaveDialog、TBevel、TControlBar、TImage、TPaintBox、TPanel、TRadioGroup、TShape、TSplitter、TTimer、TDirectoryTreeView、TFileEdit、TFileHistoryComboBox、TFileIconView、TFileListView、TFilterComboBox、TDrawGrid、TImageList、TMaskEdit、TMainMenu、TPopupMenu、TButton、TCheckBox、TComboBox、TEdit、TGroupBox、TLabel、TLCDNumber、TListBox、TMemo、TRadioButton、TScrollBar

dcldb70.bpl(Borland Database COmponents)
包括的控件:TDdataSourse、TDBCtrlGrid、TDBCheckBox、TDBComboBox、TDBEdit、TDBImage、TDBListBox、TDBLookupComboBox、TDBLookupListBox、TDBMemo、TDBNavigator、TDBRadioGroup、TDBRichEdit、TDBText、TDBGrid

dclmcn70.bpl(Borland DataSnap Connection Components)
包括的控件:TConnectionBroker、TDCOMConnection、TSharedConnection、TSimpleObjectBroker、TSocketConnection、TWebConnection、TLocalConnection

dcldbx70.bpl(Borland dbExpress Components)包括的控件:TSQLConnection、TSQLDataSet、TSQLMonitor、TSQLQuery、TSQLStoredProc、TSQLTable

dcldss70.bpl(Borland Decision Cube Components)
包括的控件:TDecisionCube、TDecisioinSource、TDecisionGraph、TDecisionGrid、TDecisionPivot、TDecisionQuery

ibevnt70.bpl(Borland Interbase Event Alerter Component)
包括的控件:TIBEventAlerter

dclnet70.bpl(Borland Internet Components)
包括的控件:TQueryTableProducer、TDataSetTableProducer、TSQLQueryTableProducer、TDataSetPageProducer、TWebDispatcher、TPageProducer、TTcpClient、TTcpServer、TUdpSocket、TXMLDocument

dclisp70.bpl(Borland Internet Solutions Pack Components)
包括的控件:TFTP、THTML、THTTP、TNNTP、TPOP、TSMTP、TTCP、TUDP

dclwbm70.bpl(Borland InternetExpress Components)
包括的控件:TInetXPageProducer、TMidasPageProducer、TXMLBroker、TXMLTransform、TXMLTransformClient、TXMLTransformProvider

dclmid70.bpl(Borland MyBase DataAccess Components)
包括的控件:TClientDataSet、TDataSetProvider

dclsmp70.bpl(Borland Sample Components)
包括的控件:TCalendar、TColorGrid、TDirectoryOutline、TGauge、TSpinButton、TSpinEdit

dclocx70.bpl(Borland Sample Imported ActiveX Controls)
包括的控件:TChartfx、TF1Book、TVtChart、TVSSpell

dcldbxcds70.bpl(Borland SimpleDataset Component(DBX))
包括的控件:TSimpleDataSet

dclsoap70.bpl(Borland SOAP Components)
包括的控件:TOPToSoapDomConvert、TSoapConnectoin、THTTPRIO、THTTPSoapPascalInvoker、THTTPReqResp、THTTPSoapDispatcher、TWSDLHTMLPublish

dclsockets70.bpl(Borland Socket Components)
包括的控件:TClientSocket、TServerSocket

dclstd70.bpl(Borland Standard Components)
包括的控件:TActionList、TApplicationEvents、TBitBtn、TSpeedButton、TCheckListBox、TCOMAdminCatalog、TAnimate、TComboBoxEx、TCoolbar、TDateTimePicker、THeaderControl、THotKey、TListView、TMonthCalendar、TPageControl、TPageScroller、TProgressBar、TRichEdit、TStatusBar、TTabControl、TToolBar、TTrackBar、TTreeView、TUpDown、TImageList、TDdeClientConv、TDdeClientItem、TDdeServerConv、TDdeServeritem、TColorDialog、TFindDialog、TFontDialog、TOoenDialog、TPageSetupDialog、TPrintDialog、TPrinterSetupDialog、TReplaceDialog、TSaveDialog、TBevel、TColorBox、TControlBar、TImage、TLabeledEdit、TPaintBox、TPanel、TRadioGroup、TShape、TSplitter、TTimer、TOpenPictureDialog、TSavePictureDialog、TScrollBox、TDrawGrid、TStringGrid、TMaskEdit、TMainMenu、TmediaPlayer、TOleContainer、TButton、TCheckBox、TComboBox、TEdit、TGroupBox、TLabel、TListBox、TMemo、TRadioButton、TScrollBar、TStaticText、TValueListEditor、TXPManifest

dclwebsnap70.bpl(Borland WebSnap Components)
包括的控件:TDataSetAdapter、TDataSetValuesList、TAdapterPageProducer、TAdapter、TApplicationAdapter、TEndUserAdapter、TEndUserSessionAdapter、TLoginFormAdapter、TPagedAdapter、TStringsValuesList、TAdapterDispatcher、TLocateFileService、TPageDispatcher、TWebAppComponents、TSessionsService、TWebUserList、TXSLPageProducer

dcl31w70.bpl(Delphi1.0 Compatibility Components)
包括的控件:THeader、TNotebook、TDirectoryListBox、TDriveComboBox、TFileListBox、TFilterComboBox、TOutline、TTabbedNotebook、TTabSet

DCLIB70.bpl(InterBase DataAccess Components)
包括的控件:TIbClientDataSet、TIBDataSet、TIBDatabase、TIBTransaction、TIBDatabaseinfo、TIBevents、TIBExtract、TIBQuery、TIBSQL、TIBSQLMonitor、TIBStoredProc、TIBTable、TIBUpdateSQL

dclindy70.bpl(Internet Direct(Indy)for D7 Property and Component Editors)
包括的控件:TIdAntiFreeze、TIdBlockCipherIntercept、TIdChargenServer、TIdChargenUDPServer、TIdDecodeMIME、TIdEncodeMIME、...

dclie70.bpl(Internet Explorer Components)
包括的控件:TWebBrowser

dclIntraweb_50_70.bpl(Intraweb 5.0 Design Package for Delphi7)
包括的控件:TIWClientSideDataset、TIWCheckBox、TIWButton、TIWEdit...

dcloffice2k70.bpl(Microsoft Office 2000 Sample Automation Server Wrapper Components)
包括的控件:TAccessApplicatoin、TAccessForm、TAccessReferences、TAccessReport、TClass_、TBinder、TExcelApplication、TExcelChart、TExcelOLEOBject、EExcelQueryTable、TExcelWorkbook、TExcelWorksheet、Tmaster、TPowerPointApplication、TPowerPointPresentation、TPowerPointSlide、TContactItem、TDistListItem、TDocumentItem、TExplorers、TFolders、TInspectors、TItems、TJournalItem、TnameSpace、TOutlookApplication、TOutlookBarGroups、TOutlookBarPane、TOutlookBarShortcuts、TPostItem、TRemoteItem、TReportItem、TTaskRequestAcceptItem、TTaskRequestAcceptItem、TTaskRequestDeclineItem、TTaskRequestItem、TTaskRequestUpdateItem、TWordApplication、TWordDocument、TWordFont、TWordLetterContent、TWordParagraphFormat

dclqrt70.bpl(QuickReport Components)
包括的控件:TQRDBImage、TQRDBRichText、TQRDBText、TQRExpr、TQRExprMemo、TQRImage、TQRLabel、TQRLabel、TQRMemo、TQRRichText、TQRShape、TQRSysData、TQRCSVFilter、TQRHTMLFilter、TQRTextFilter、TQRPreview、TQRBand、TQRChildBand、TQRCompositeReport、TQRGroup、TQRStringsBand、TQRSubDetail、TQuickRep

dclRave70.bpl(Rave Reports DE 5.0 Package)
包括的控件:TRvCustomConnection、TRvQueryConnection、TRvTableConnection、TRvDataSetConnection、TRvNDRWrite、TRvProject、TRvRenderHTML、TRvRenderPDF、TRvRenderPreview、TRvRenderPrinter、TRvRenderRTF、TRvRenderText、TRvSystem、TRvCustomConnection、TRvTableConnection、TRvDataSetConnection、TRvNDRWriter、TRvProject

dclshlctrls70.bpl(Shell Control Property and Component Editors)
包括的控件:TShellChangeNotifier、TShellComboBox、TShellListView、TShellTreeview

dcltee70.bpl(TeeChart Components)
包括的控件:TChart、TDBChart

dcltqr70.bpl(TeeChart for QuickReport Components)
包括的控件:TQRChart

---------------------------------------
Delphi7中QuickReport的安装:
点击Componnet菜单的Install Packages,点击Add...添加QuickReport Components
的路径X:/Borland/Delphi7/Bin/dclqrt70.bpl(X为Delphi的安装路径) 

dclsockets70.bpl FastNet

Delphi7中网络组件已由Indy代替,与Rave代替QuickReport一样, FastNet安装:
点击Componnet菜单的Install Packages,点击Add...添加QuickReport Components
的路径X:/Borland/Delphi7/Bin/dclsockets70.bpl(X为Delphi的安装路径) 

- 作者: hongjiang1978 2005年05月14日, 星期六 10:58  回复(0) |  引用(0) 加入博采
delphi中第三方控件的安装方法 1 只有一个DCU文件的组件。DCU文件是编译好的单元文件,这样的组件是作者不想把源码公布。一般来说,作者必须说明此组件适合Delphi的哪种版本,如果版本不对,在安装时就会出现错误。也正是因为没有源码,给使用者带来了不便,那就是一旦Delphi版本升级,此组件就不能再使用了,当然有的作者给出了几种版本的DCU文件,用户根据需要选择使用。这样的组件的安装方法是:在Component菜单中,选择install component,在对话框
"into existing package"页中,单击“Unit file name”后的“Browse”按扭,在打开的文件对话框中,将“文件类型”设定为*.dcu,找到要安装的DCU文件,按OK按钮返回"into existing package"页后再按OK按钮就可以安装了。注意,此时Delphi会提示dclusr40.dpk将被重建,是否继续,OK就可以了。这里是将组件安装到dclusr40.dpk包中,此包从文件名上可以看出是用户自定义组件包,先安装到这个包中吧,下面再讲有关注意事项。安装完毕会有已经将组件注册完的提示信息以及安装到哪个组件页中的信息等,到组件面板上看看,一般会出现一个新的组件页,其中有刚安装的组件。

2、 只有PAS文件或既有PAS又有DCU文件的组件。这种组件因为有PAS文件,也就是说作者提供了源码,这就好办多了。安装的方法和上面是一样的,在文件类型中可以设定为DCU也可以设定为PAS,建议设定为PAS,这样可用你的Delphi重新编译一下,看是否会出现问题。Delphi升级后只能选择PAS文件安装,这样才能重新编译,使得组件能适应新Delphi版本。这样的组件是很值得使用的,根据心铃的经验,没有源码的组件最好不要使用,一是存在Delphi版本升级后无法使用的问题,再者当程序出现问题后用户无法调试组件来判断是否是组件中存在BUG。

3、有dpk文件的组件包。带有dpk文件的组件包一般是有多个组件构成的,也就是说安装后会有多个组件供使用,如果只有一个组件作者一般不会制成DPK文件,使用上面的方式发布就可以了。对于这样的组件包,一般来说会有详细的安装说明文件,如上面提到的RXLIB,由于组件复杂且安装时有先后顺序,作者不提供安装说明用户根本无法正确安装。如果没有安装说明文件,那么用下面的方法安装:在File菜单下,选择”OPEN…”打开dpk文件(文件类型列表框中选*.dpk),在出现的Package窗口中,工具栏上有Install按钮,按此按钮即可进行安装。如果Install按钮处于无效状态,那么先按Compile按钮编译,一般来说编译之后Install按钮就会处于有效状态,此时再按Install按钮就可以了。

4、 带有Bpl文件的组件包。一般来说这也是由多种组件构成的组件包,它其实是一个动态连接库文件(DLL)。对于这种组件包的安装方法是:在component菜单下选择“install packages”,然后单击Add按钮,在打开的文件对话框中找到相应的bpl文件打开返回后,再单击Ok按钮就可以了。

5、ActiveX控件的安装。要安装这类控件,需要先用regsvr32.exe注册,然后选择Component菜单中Import ActiveX Control项。在Import ActiveX Control打开的窗口中,只有已经注册的ActiveX控件才出现在列表中,选中一个然后按Install按钮就可以安装了。如果事先没有用regsvr32.exe注册也可以按ADD按钮找到OCX文件即时注册,注册后再进行安装。

几点说明:

1 在拿到组件后先看是否有说明文件,一般来说在说明文件中有如何安装的指导,有些还会有组件的属性、事件、方法的使用说明,这些在使用时是非常重要的。

2 在上面的组件(包)安装操作之前,最好将 *.bpl拷贝到你的System目录中,将 *.pas、*.dcu、*.dcr、*.dp?拷贝到Delphi的Lib目录中再进行。

3 前面我们提到安装DCU组件时,选用的是已经存在的dclusr40.dpk,当然也可以选择安装到一个新的包中,如果选择新包,需要先取一个名字比如DEMO,事实上安装完毕后用户可以找到的是Demo.bpl,而找不到DEMO.DPK。假如你已经将一个组件安装到dclusr40.dpk中了,还想再安装一个组件,如果再安装到dclusr40.dpk中,安装后你得到提示,原来安装的那个组件已经被取消注册,你将无法使用了。这样不就成了只能安装一个组件了吗?除非你再安装到一个新的包中才可以两个组件同时使用。当然每安装一个组件生成一个新的BPL文件也未偿不可,但BPL文件就增加许多。能否在dclusr40.dpk中多安装几个组件呢?当然是可以的。方法如下:用File菜单下的OPEN打开dclusr40.dpk文件,单击ADD按钮,在打开的对话框中选择ADD UNIT页面,按Unit file name后的“Browse”按钮打开组件单元文件,OK即可,用此种方法这样可添加多个组件的单元文件,添加完毕,按一下编译按钮,然后再按Install按钮即可,如果单元文件是编译好的(DCU)可以直接按安装按钮。

4 组件的删除。光会安装可不行,还要会删除呀。很简单,在component菜单下,选择install packages,在列表中找到安装所在的Bpl,按Remove按钮,ok!再把Bpl文件删掉就彻底了,如果不删除BPL文件,下次可以按安装BPL组件的方法再安装使用
---------------------------------------------------------------

在delphi中菜单里有import package or import component(?)
一个是导入控件(如stardard 下的一个button控件),一个是导入一个控件条(如stardard,win3.1),你可以try try.实践出真知吗!

 

 

- 作者: hongjiang1978 2005年05月14日, 星期六 09:30  回复(0) |  引用(0) 加入博采
Delphi中关于菜单的几个技巧 本人在学习使用Delphi中,遇到了一些关于菜单的编程问题,其中一些比较由代表性或比较实用,先把它从笔记中整理出来,与大家分享,请多多指教。


-- 1
将菜单项移到菜单栏的最右边

  在一些应用程序中,常把一些特殊的菜单项放在菜单栏的最右边(如WPS2000 中的"定制界面"菜单,一些应用程序的帮助菜单),这些菜单项放在菜单栏(menu bar)的右边比较好。Delphi中虽然没有直接提供(呵呵,也许是我没找到)把菜单放在菜单栏右边的函数,但是Delphi的Windows单元封装了可以实现这种效果的Windows API函数(ModifyMenu、GetMenuItemInfo)。因此,我们在Delphi中可以直接使这些函数来实现这种效果。
  使用ModifyMenu和GetMenuItemInfo都可以将菜单项移到菜单栏的最右边,那么选那个较好呢?据 Windows SDK 文档:
  ModifyMenu函数可以改变一个已经存在的菜单项的设置,这个函数用于指定一个菜单的标题、显示外观等项目,不过,ModifyMenu函数现在已经被功能更强大的SetMenuItemInfo函数取代。虽然如此,如果你的程序不需要SetMenuItemInfo函数提供的扩展功能,你仍旧可以继续使用ModifyMenu函数。
  ModifyMenu函数支持 Windows 32、9x、NT/2000。
  SetMenuItemInfo函数支持 Windows 9x、NT/2000,不支持windows 32(较早版本也不支持NT/2000)。
  另外,SetMenuItemInfo函数功能比ModifyMenu函数强大,不过使用函数SetMenuItemInfo需要的参数也比ModifyMenu函数复杂的多。所以这里我依然使用比较简单的ModifyMenu函数来实现。
  ModifyMenu函数原型为:
  BOOL ModifyMenu(
    HMENU hMnu, // handle of menu
    UINT uPosition, // menu item to modify
    UINT uFlags, // menu item flags
    UINT uIDNewItem, // menu item identifier or handle of drop-down menu or submenu
    LPCTSTR lpNewItem // menu item content
    );
  第一个参数hMENU 指的是要修改的菜单的句柄(如:MainMenu1.Handle);
  第二个参数uPosition 指的是要修改的菜单项索引值(菜单栏左边第一个其值为零,从左向右递增,最大值为菜单项的总数减一);
  第三个参数uFlags指的是(第二个参数所指的菜单项修改后的)新菜单项的状态;
  第四个参数uIDNewItem 是指向新菜单的句柄;
  第五个参数lpNewItem指的是新菜单的标题。
  举例如下:
  创建一个带有菜单的新工程,设其MainMenu组件的名字为MainMenu1,其中要移到菜单栏的最右边的那个菜单的名字为Help1。
  在窗体的OnCreate时间的处理程序中加入以下代码
  procedure TForm1.FormCreate(Sender: TObject);
  begin
   ModifyMenu(MainMenu1.Handle,2,
       MF_BYPOSITION or MF_HELP,
       Help1.Handle,Pchar(Help1.Caption));
      //其中:MF_HELP 参数决定菜单项(Help1)在窗口的最右端显示。
  end;
  然后运行,看看效果如何

-- 2
定制系统菜单

  常见的应用程序的主窗体中,利用鼠标左键点击左上角的图标,会弹出一个系统菜单,这个菜单一定程度上给了我们很大方便,问题是那些都是缺省的系统菜单命令,对于我们来说没有太大的帮助。当然,我们可以自己定制系统菜单,加上我们需要的东西,在Delphi 中,窗体组件并没有提供系统菜单对应的组件,所以定制系统菜单时就有我们自己动手用Windows API函数来实现。Windows API函数中,常用于对菜单操作的函数有:
  AppendMenu 在现有的菜单项尾部插入一个新菜单项;
  DeleteMenu 删除菜单中一个现有的菜单项,并清除该项;
  RemoveMenu 在现有的菜单项中删除某一项;
  InsertMenu 在现有的菜单项中插入一个新项;
  ModifyMenu 修改一个现有菜单项;
  这些函数用法都是类似的上面已经说了ModifyMenu函数的用法,下面仅用AppendMenu函数在系统菜单中添加一个关于菜单来说明,虽然它本身是没有什么意义的,但希望可以起到抛砖引玉的作用。
  AppendMenu 函数原型:
  BOOL AppendMenu(
     HMENU hMenu, // 要定制的菜单句柄
     UINT uFlags, // 怎样定制菜单项
     UINT uIDNewItem, // 要定制的菜单项标识或子菜单句柄
     LPCTSTR lpNewItem // 要定制的菜单项(字串)
    );
  在 AppendMenu 函数里,lpNewItem 和 uIDNewItem 参数依赖 uFlags 的不同标志而有所变化。
  唯一限制:系统菜单中添加的菜单项的ID值(uIDNewItem)必须小于 $F000(十进制:61440);否则会与Windows系统菜单命令所使用的ID值相冲突。还要记住当为这些新菜单在窗口过程中处理WM_SYSCOMMAND消息时,必须把其它的WM_SYSCOMMAND消息发给DefWindowsProc(在Delphi中秩序在事件处理程序最后加入一句 Inherited;),否则,嘿嘿,你试试就知道了。
  首先创建一个新工程,因为要用到Menus单元中的内容,故在文件Unit1.pas的uses语句中加入Menus。
  uses
   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ComCtrls,  Menus;
  然后在窗体Form1的OnCreate事件处理过程加入以下代码:
  procedure TForm1.FormCreate(Sender: TObject);
  var hSysMenu:hMENU;
  begin
   hSysMenu:=GetSystemMenu(Handle,False);//得到系统菜单句柄
   AppendMenu(hSysMenu,MF_SEPARATOR,0,'');//添加一个分隔符
   AppendMenu(hSysMenu,MF_STRING,3,'关于(&A)');
  end;
  在TForm1的类型定义中,添加系统菜单中新建菜单项的OnClick事件的处理过程的声明(即对消息WM_SYSCOMMAND的处理声明):
  type
   TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
   private
    procedure SysMenuCommand(var Msg:TWMMENUSELECT);
     message WM_SYSCOMMAND;
    { Private declarations }
   public
    { Public declarations }
   end;
  接着按Shift+Ctrl+C完成类声明。在其中填入以下代码:
  procedure TForm1.SysMenuCommand(var Msg: TWMMENUSELECT);
  begin
   if Msg.IDItem=3 then
     MessageBox(0,'A Poor-Person''s Menu Program'+#13+
          ' Copyright Skyey ,2000','Skyey',
         MB_OK+MB_ICONINFORMATION);
   Inherited;
  end;
  编译、运行程序,测试其效果。
  附:uFlags 一些定义值://选译自Delphi 5带的Windows SDK 帮助
  MF_BITMAP 指明该菜单项是一位图,在 lpNewItem 参数代表位图句柄
  MF_CHECKED 在菜单项的前面放上一个"选中"标记
  MF_DISABLED 屏蔽该菜单项,但不使它变成灰色
  MF_ENABLED 使该菜单项有效,与 MF_DISABLED 相反
  MF_GRAYED 除了有 MF_DISABLED 的作用以外,还把该菜单项变灰
  MF_MENUBREAK 把该菜单与现有菜单并排放在一起
  MF_MENUBARBREAK 与MF_MENUBREAK 相同,除了在中间放一条竖线外
  MF_OWNERDRAW 表明该菜单项为自绘菜单项,还必须处理一切的显示、更新问题
  MF_POPUP 该菜单项为一子菜单,uIDNewItem 参数代表其句柄
  MF_SEPARATOR 在菜单项画上一分割线
  MF_STRING 该菜单项是一文本字串,lpNewItem 是其内容
  MF_UNCHECKED 取消该菜单项前面的"选中"标记
  以下几组标志中每组的标志不能同时使用:
  < 1> MF_DISABLED, MF_ENABLED, and MF_GRAYED
  < 2> MF_BITMAP, MF_STRING, and MF_OWNERDRAW
  < 3> MF_MENUBARBREAK and MF_MENUBREAK
  < 4> MF_CHECKED and MF_UNCHECKED

-- 3
为菜单动态定义快捷键

  其实就是改变菜单的ShortCut属性,在程序中加入一个HotKey组件,然后把其HotKey属性赋给菜单的ShortCut属性即可。如:
  procedure TForm1.BtnChange1Click(Sender: TObject);
  begin
   New1.ShortCut:=Hotkey1.HotKey;
  end;
  如果你只需要程序自行更改有限的几个快捷键而不需要用户自己改变,那么也可以不用HotKey组件,直接把一个TShortCut类型的数值赋给菜单的ShortCut属性即可。如:
  procedure TForm1.BtnChange1Click(Sender: TObject);
  begin
   New1.ShortCut:= 32833;//就是Alt+A
  end;
  一个快捷键的值可以按下面的方法在设计时得到:先在设计时改变菜单的ShortCut属性的为你需要的快捷键,然后在窗体上-> 右键-> View as Text,在DFM文件中找到那个组件,那个ShortCut后面的就是。如:需要Ctrl+Alt+N
  object New1: TMenuItem
   Caption = '&New'
   ShortCut = 49230 //就是这个
   OnClick = New1Click
  end

-- 4
动态改变菜单

  就是改变菜单项的Enabled属性和Visible属性。这两个属性既可以在设计时改变,也可以在运行时改变。
  如果将Enabled属性设置为False,则菜单项呈灰色状态,不可用;如果设置为True,则菜单项处于正常能用的状态。
  如果将Visible属性设置为False,则该菜单项在运行时不显示;如果设置为True,则该菜单项显示。
  如:New1.Enabled:=False;//New菜单项变成灰色,菜单现在不可用
  New1.Enabled:=True; //New菜单项现在可以使用
  New1.Visible:=False //New菜单项现在不显示
  New1.Visible:=True; //New菜单项现在显示
  唯一需要注意的是:Visible和Enabled属性时两个互相独立的属性,二者互不干扰,如果一个菜单拥有一个快捷键且其Enabled属性为True,即使其Visible属性为False(即运行时不可见),仍可以用快捷键来访问。
  在程序运行期间,修改菜单项的这两个属性,即可以动态地改变菜单显示。

-- 5
获取用户错误按键信息

  如果用户按Alt和一个与菜单项不匹配的字符时,或者当显示弹出式菜单而用户按下一个与弹出式菜单里的项不匹配的字符键时。我们怎么知道用户按错了键,又怎么知道用户按了那个键呢?
  事实上,当发生上面假设的情况时,Windows会发出一个WM_MENUCHAR消息,通常我们不需要处理这个消息,Windows程序通常会把它传给DefWindowProc,它一般给Windows返回0,即使Windows发出一个短的蜂鸣声。如果我们需要处理上面假设的情况时,只要拦截这个消息就可以了。
  让我们先了解一下这个消息的参数:
  WM_MENUCHAR
   LOWORD(wParam); //即用户按键的ASCII码
   HIWORD(wParam); //选择码
   lParam; // 菜单句柄
  选择码含义:
  0: 不显示弹出菜单;
  MF_POPUP: 显示下拉菜单、子菜单、快捷菜单(弹出式菜单)
  MF_SYSMENU: 显示系统弹出式菜单
  消息返回值:
  0: 通知Windows丢弃用户按的这个字符并发出一个短的蜂鸣声;
  1: 通知Windows应该关闭当前活动菜单;
  2: 通知Windows返回一个相对于菜单项的零基点的低位字,它由Windows决定。
  了解这一点后,让我们具体做一下:
  创建一个带有菜单的新工程,在窗体上放一个Memo组件(Name:Memo1)在窗体的公有变量后加入消息的声明部分:
  public
   procedure MMenuChar(var Msg:TMessage);message WM_MENUCHAR;
   { Public declarations }
  end;
  按Shift+Ctrl+C完成类声明。在其中填入以下代码:
  procedure TForm1.MMenuChar(var Msg: TMessage);
  begin
   Memo1.Lines.Add(Chr(LOWORD(Msg.WParam)));
   Memo1.Lines.Add(IntToStr(HIWORD(Msg.WParam)));
   Msg.Result:=0;
  end;
  编译、链接并运行程序,测试其效果。

- 作者: hongjiang1978 2005年05月14日, 星期六 09:26

14对TTreeView里单个的TTreeNode的颜色进行控制

(from google groups http://groups.google.com/group/borland.public.delphi.objectpascal/browse_thread/thread/7b86380a482569e9/8e8f91b176ca4d37?lnk=st&q=delphi+treenode+font+color&rnum=7#8e8f91b176ca4d37)

Change color in TTreeView
All 6 messages in topic - view as tree
        From:        J Leavitt - view profile
Date:        Tues, Oct 5 1999 12:00 am
Not yet rated
     
show options


I posted a message asking how to change the color of a node in TTreeView
last week and received a reply something like:

In Customdrawitem event

If something then
    canvas.brush.color := somecolor
else
    canvas.brush.color := somothercolor;

I can't get this to work.

Any help or other suggestions?

Reply     Rate this post: 


        From:        Steve Zimmelman - view profile
Date:        Tues, Oct 5 1999 12:00 am
Not yet rated
     
show options


It's actually pretty easy.  In the OnCustomDrawItem event you can change the
Brush (Background) color or the Font (Foreground) color like this:

Canvas.Brush.Color := clRed
Canvas.Font.Color := clWhite

If there are conditions for specific nodes to be certain colors, you'll need
to do some checking of your own and set them accordingly.  I've used a
couple of different TList's to store nodes that should be different colors,
and stored the actual node pointer in the Data element of the Tlist.
Something like this:

// these should be in the scope of the entire unit.
Var
   tlRed,tlGreen: Tlist ;

Procedure MyProc ;
Var
   TrRoot,trChild : TTreeNode ;
Begin

tlRed := Tlist.Create ;
tlGreen:= Tlist.Create;

// Root will be Red
TrRoot := TreeView.Items.Add(nil,'This is a Root Node');
tlRed.Add(TrRoot);

// Child will be Green
TrChild:=TreeView1.Item.AddChild(TrRoot,'ChildNode');
tlGreen.Add(TrChild);

End;

Then in the OnCustomDrawItem of treeview you can check the Tlist's for the
current Node and change it's color.

procedure OnCustomDrawItem(Sender: TCustomTreeView; Node: TTreeNode;
                    State: TCustomDrawState; var DefaultDraw: Boolean);
Begin
   If FindNode(tlRed,Node) Then
      Canvas.Font.Color := clRed
   Else If FindNode(tlGreen,Node) Then
      Canvas.Font.Color := clGreen ;
End;

Function FindNode(tr:TreeNode;tl:Tlist): Boolean;
Var i : Integer
Begin
   Result := False ;
   For i := 0 To tr.Count-1 Do Begin
      If tl.Items[i] = tr Then Begin
         Result := True ;
         Break;
      End;
   End;
End;

Don't forget to Free any Tlist objects you create.  Oh, and, this is
untested code...<g>

Hope this helps.

-Steve-

J Leavitt <john.leav...@smed.com> wrote in message

news:7tdj3a$d2717@forums.borland.com...
I posted a message asking how to change the color of a node in TTreeView
last week and received a reply something like:

In Customdrawitem event

If something then
    canvas.brush.color := somecolor
else
    canvas.brush.color := somothercolor;

I can't get this to work.

Any help or other suggestions?

Reply     Rate this post: 


        From:        Greg Lorriman - view profile
Date:        Wed, Oct 6 1999 3:00 pm
Not yet rated
     
show options



J Leavitt <john.leav...@smed.com> wrote in message

news:7tdj3a$d2717@forums.borland.com...

> I posted a message asking how to change the color of a node in TTreeView
> last week and received a reply something like:

> In Customdrawitem event

> If something then
>     canvas.brush.color := somecolor
> else
>     canvas.brush.color := somothercolor;

> I can't get this to work.

> Any help or other suggestions?

the code above, as it stands, would mess with the forms canvas not the
treeview. Are you doing a "with treeview do begin"?

--
Greg Lorriman
Handy, free utils at http://www.lorriman.demon.co.uk

Reply     Rate this post: 


        From:        Steve Zimmelman - view profile
Date:        Wed, Oct 6 1999 12:00 am
Not yet rated
     
show options


Greg's correct.  I left out the With statement in the OnCustomDrawItem.  It
should be:

procedure OnCustomDrawItem(Sender: TCustomTreeView; Node: TTreeNode;
                    State: TCustomDrawState; var DefaultDraw: Boolean);
Begin

WIth Sender Do Begin
   If FindNode(tlRed,Node) Then
      Canvas.Font.Color := clRed
   Else If FindNode(tlGreen,Node) Then
      Canvas.Font.Color := clGreen ;
End;

End;

>I just wanted to change the color of a couple of the nodes if they met
>certain requirements.

The FindNode function in this case is the criteria.  You can certainly
change this to meet whatever needs you have.  I  agree with you, in some
cases colors are less crowed.

-Steve-

Reply     Rate this post: 


        From:        J Leavitt - view profile
Date:        Wed, Oct 6 1999 12:00 am
Not yet rated
     
show options


No I'm not.  Right now I'm not doing anything other than adding it to the
tree like this:

    tmp := mTreeList.Add(mNode);    // add the pointer to the list.  mNode
is a structure.
    tvFunctions.Items.AddChildObject(tnParent, ListItem.Caption,
mTreeList[tmp]);

I just wanted to change the color of a couple of the nodes if they met
certain requirements.  Maybe I should do something else like stateImages?  I
just thought a color would be less crowded.

Thanks.

Reply     Rate this post: 


        From:        Steve Zimmelman - view profile
Date:        Wed, Oct 6 1999 12:00 am
Not yet rated
     
show options



>the code above, as it stands, would mess with the forms canvas not the
>treeview. Are you doing a "with treeview do begin"?

You're right.  I must have been a bit too tired...<g>

-Steve-

Reply     Rate this post:
15delphi中用TStrings来实现名值对问题,TStrings有names和values两个属性

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值