線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:8693
推到 Plurk!
推到 Facebook!

一位Delphi發燒網友的編程心得

 
jackkcg
站務副站長


發表:891
回覆:1050
積分:848
註冊:2002-03-23

發送簡訊給我
#1 引用回覆 回覆 發表時間:2003-02-11 19:44:23 IP:61.221.xxx.xxx 未訂閱
此為轉貼資料 一位Delphi發燒網友的編程心得 心得00 98.5.24 INI文件的操作要點 (1)在interface關鍵字後的uses子句中加入 uses ...,inifiles; (2)設置變數:var inifile:=TIniFile; (3)使用前,一定要先做: inifile:=TIniFile.Create(inifilename); 我在這裏繞了個彎子,寫成 inifile.Create(inifilename); TShiftState用來檢測CTRL,ALT,Shift,以及滑鼠按鍵的狀態, 常常用在鍵盤或滑鼠的事件處理程式之中。 DCU文件(編譯的庫單元)的重用 (1)在interface裏的uses子句中引用。如Windows,Dialogs, 等等,要求被引用的DCU一定要放在Delphi 3\Lib子目錄中。 (2)在implementation裏的uses子句中引用。如果是自行編寫的 DCU文件,應採用這一方式,並將被引用的DCU文件放入當前 工程所在的子目錄中。 executefile函數(在FmxUtils.DCU中定義)不能用在FormCreate 事件中。真奇怪...... 內置的版本號控制功能 在Project Options中的VersionInfo項裏,有版本資訊的定制, 包括一個有趣的版本號自動增加功能(Auto-increment build number),即每Build一次,版本號中的Build Number加1。選中 Include version information in project,編譯,用資源管 理器裏找到生成的.exe文件,點右鍵,查看“屬性”一項,就 會看到在屬性中多了一頁“版本”,裏面就是你剛才輸入的各 項內容。 98.5.17 定制Speedbar 右鍵點擊左上角的加速鍵條(speedbar),選中Properties, 在列表框中找到你想要加入speedbar的命令按鈕,將它拖到 speedbar上的合適位置即可。如果speedbar上沒有多餘的空間 來容納新的按鈕,可把滑鼠在speedbar右框處變爲雙向箭頭的 形狀,向右拖動一段距離,就可騰出空間。如想刪除speedbar 上的某個按鈕,可簡單地把它拖出speedbar的範圍,就能刪除。 98.5.13 計算出的欄位 在寫一個程式時,我要在DBGrid中顯示出一個memo的部分資訊,當我把那個 memo欄位放進去後,運行時只能顯示出“(memo)”字樣。從書上找到計算字 段的用法後,我在TTable中增加一個計算欄位MemoHeader,寬度爲40,在此 TTable的OnCalcFields事件中輸入: with MyTable do FieldByName('memoheader').asstring:=FieldByName('memo').asstring; 在DBGrid中放入MemoHeader,運行,OK! 欄位編輯器 解決了上面的問題後,我繼續學習欄位編輯器的作用。原來,DELPHI通過字 段編輯器,近乎完美地實現了資料庫的欄位級的控制,這包括: 1)欄位在DBGrid中標題、寬度、能否可見; 2)欄位的顯示格式和編輯時輸入的過濾條件; 3)欄位是否唯讀; 4)欄位的類型:資料欄位/計算欄位/查詢欄位/內部計算欄位; 5)欄位的顯示/賦值/修改等事件的定制。 Delphi真的...很強喲! 98.5.7 設計Form時的快捷鍵 Del 刪除所選元件 Esc 選擇當前元件的容器(通常是Panel,Group或Form) F11 在Form或Unit和物件檢查器之間切換 F12 在Form和代碼編輯器間切換 Ctrl-F12 顯示“查看Unit”對話方塊 Shift-F12 顯示“查看Form”對話方塊 TAB 下一個元件 Shift-TAB 上一個元件 方向鍵 選中此方向上最近的元件 Ctrl-方向鍵 將所選元件移動一個點 Shift-方向鍵 將所選元件改變一個點的大小 Ctrl-Shift-方向鍵 將所選元件移動一個格 Shift-click 按住Shift鍵再用滑鼠點擊元件,可以選擇多個元件。 --= 下面這條是我摸索出來的 =-- Ctrl-drag 按住Ctrl鍵在一個容器元件(如Panel,QReport,Groupbox等) 裏拖動滑鼠,可強制選擇滑鼠拖過的矩形框中的所有屬於此容 器的可視元件但不包括該容器元件。 98.5.5 使用QReport的若干經驗 1)QuickRep1.DataSet:=query1 不然無輸出結果 2)從qrpt2man.doc中查知,格式化輸出結果的方法是: 在QRDBText.Mask中設爲.00;0,將使輸出帶兩位小數。 3)設置Group時,先加入一個QGroup,再加入一個QRBand,將QGroup的 FooterBand設爲剛才的QRBand,就可將其聯繫起來。 4)在Group中列印的合計數,其ResetAfterPrint設爲True,可實現分組合計。 98.5.4 看了《中國電腦報》4月30日軟體與應用版的《Delphi中創建Splash視窗》, 心裏又是高興又是惋惜。高興的是我已經知道了這個方法(說明我水平不低:) 惋惜的是我應該寫一篇同類的稿件,說不定... (見我在4月16日的專題) 98.4.30 今天新學了個format函數,對給定的字串格式化,返回結果字串: format('%*.*f',[8,2,123.456]); //等價於format('%*8.2f',[123.456]) format('%d %d %0:d %d'[10,20]); 取得系統資訊 GetSystemInfo 98.4.29 (以下TIPS取自DelphiTI.zip) 播放一個wav文件 use mmsystem; SndPlaySound('hello.wav',SND_FILENAME or SND_SYNC) 優化WIN95下的ORACLE連接 在[ORA_HOME]\NETWORK\ADMIN\SQLNET.ORA中增加一行 AUTOMATIC_IPC=OFF (據說可將連接時間從15秒縮短至3秒!不過我試過似乎沒啥改變...) 設置WIN95的牆紙 var s:string; s:='c:\windows\athena.bmp'; SystemParametersInfo(SPI_SETDESKWALLPAPER,0,Pchar(s),0); InputBox,InputQuery和ShowMessage函數的威力 uses dialogs; var s,s1:string; b:boolean; begin s:=trim(Inputbox('NewPassword','Password','masterkey')); b:=s<>''; s1:=s; if b then b:=InputQuery('Confirm Password','Password',s1); if not b or (s1<>s) then ShowMessage('Password Failed'); end; // 試試吧! 使你的form適應不同的顯示解析度 假設你在800*600的解析度下設計的form,第一步: inplementation const ScreenWidth: LongInt = 800; {I designed my form in 800x600 mode.} ScreenHeight: LongInt = 600; {$R *.DFM} procedure TForm1.FormCreate(Sender: TObject); begin scaled := true; if (screen.width <> ScreenWidth) then begin height := longint(height) * longint(screen.height) div ScreenHeight; width := longint(width) * longint(screen.width) div ScreenWidth; scaleBy(screen.width, ScreenWidth); end; end; 下一步,要讓每個子控制的字體改變到合適的大小: type TFooClass = class(TControl); { needed to get at protected } { font property } var i: integer; begin for i := ControlCount - 1 downto 0 do TFooClass(Controls[i]).Font.Size := (NewFormWidth div OldFormWidth) * TFooClass(Controls[i]).Font.Size; end; 98.4.27 用raise引發一個錯誤處理常式 示例:先給出下面的定義 type EPasswordInvalid=class(Exception); 這樣你就可以隨時引發一個"password invalid"的例外: if Password<>CorrectPassword then raise EPasswordInvalid.Create('Increect Password entered'); 運行後,出現資訊框 Project Project1.exe raise exception class EPasswordInvalid with message 'Incorrect Password entered'. Process stopped. Use step or run to continue. 再按Run按鈕,出現一個資訊框: Incorrect Password entered. 1998.4.26 從DEMO常式中學到的若干小技巧 在demo\internet\http\webbrows\main.pas中, procedure TForm1.DocumentSourceClick(Sender:Tobject); begin with DocSourceForm do begin show; // 顯示HTML源碼的FORM Memo1.lines.clear; // 清空memo1中內容 Memo1.lines.add(HTML1.SourceText); // 植入源碼 Memo1.SelStart:=0 // *** SendMessage(Memo1.Handle, // Memo1的窗口控制碼 EM_ScrollCaret //將Edit Control中的caret游標滾動到視野中 0,0 //這兩個參數暫不使用 end; end; (此SendMessage系一WinAPI調用,給一個或一組視窗發送消息,直到 相應視窗處理此消息後才有返回值。相似的另一函數爲PostMessage, 它將消息放入消息佇列中後立即返回。) *** 清空當前選擇並將游標移動到指定字元(0代表第一個字元)。如同時 設memo1.sellength爲一非0值,可選擇一段文本。 1998.4.23 幾個有關子目錄的操作的過程: MkDir(str); ChDir(str); GetDir(DriveID,str); SetCurrentDir(str); IOResult --上面幾個程序呼叫成功即返回0值 1998.4.16 在demo\db下有一MastApp,演示了如何在啓動一個大程式前期顯示一個小小封面 splash.pas: begin SplashForm:=TsplashForm.Create(Application); SplashForm.show; SplashForm.update; //這一句強制調用WinAPI的UpdateWindow函數 ... ... end. 另一種在函數中返回值的方法: Function MyFunc(...):integer; begin ... ... MyFunc:=8; //只要對函數名賦值,函數立即返回。 end; 幾個常用函數 MessageBeep --播放Windows標準音效檔案 MessageBox --顯示一個資訊對話方塊 TWinControl類: SetFocus 設置爲當前輸入焦點 AsString 比 AsInteger 在表間欄位互相賦值時更有效,更不易出錯。 Application.Message('errtext','errcaption',mb_OK);彈出一對話方塊,按OK確定。 1998.4.15 用ExecuteFile執行一外部程式 uses ShellAPI; // 提供 ShellExecute 函數在demos\doc\filmanex目錄下,有一FMXUtils中提供各種文件操作增強函數, 其中Function ExecuteFile(filename,params,WDir,SW_SHOW) 可運行外部程式。 1998.4.10 連入遠端ORACLE伺服器(續) 今天我發現,只需在TDatabase元件中,設DriverName爲ORACLE,在Parms中加入 Server Name=orac, 照樣能連入遠端的ORACLE伺服器,根本不需要設置BDE alias。 1998.4.9 發佈自己的應用程式 今天使用DELPHI自帶的Install Shield,做了一個安裝程式。在沒有裝DELPHI的 機器上安裝我做的資料庫應用程式。開始系統提示找不到別名,最後我運行了一 下Bdeadmin.exe,增設一個別名,OK! 1998.4.8 連入遠端ORACLE伺服器 今天使用BDE設置oracle, OK。Net Protocol:TNS/ServerName=orac 1998.4.6 自動登錄遠端資料庫 Database.Parms的內容如下: user name=[yourname] Database.Parms[1]:='password=yourpass' 再把Login Prompt一項設爲False,其他的就不用再說了吧? 1998.4.1 在Win95 的 ORACLE client 中增加ODBC驅動 進入ORACLE 32-bit Adminstrator,選System DSN,Add,選擇Oracle73(已在Easy Install中設好): Data Source Name: orac Description:My Oracle 7.3 ODBC SQL*Net Connect String:tns:orac --OK! 心得01 98-6-22 11:08 翻出數月前下載的一個Delphi增強元件庫rxlib.zip,照著其中的說明文件 安裝到我的Delphi3下,忽然有種感覺:要是以開發Delphi元件爲榮的人見到 rxlib.zip一定會有"既生瑜,何生亮"的感覺.這個元件庫做得實在是太好了. 98-6-19 9:26 奇怪的I/O error -- 我在開發過程中發現下面這兩條語句 assignfile(fDesc,CDDatadir describefile); reset(fDesc); 每當我第一次運行到這裏時,總會出現 I/O Error 183 的錯誤. 最後我想這也有可能是沒有清除 ioresult 的原因.在兩句之間加入 if ioresult<>0 then; oooook! 可以了. 98-6-18 11:40 值得注意的I/O error AssignFile(F, fname); Rewrite(F); 當文件 F 經 Reset(F)打開的情況下, Rewrite(F)會引發一個異常: I/O error 32 反之,經 Rewrite(F)打開, Reset(F)也會引發同一個異常. Reset(F)兩次,closefile(F),再Rewrite(F),或反之,也會引發同樣異常. 98-6-17 1:40 關於FileListBox的一個無法避免的陷阱 Delphi叫我既愛且恨。我做了個程式,是掃描光碟目錄的。用到了FileListBox元件。 每當我轉到光碟上的某個特定文件夾後,換上另一張光碟,再次掃描,FileListBox就 會報錯:File not found. 爲了這個錯誤,我調試了整整兩天!開始以爲是自己程式 中有邏輯錯誤,可無論怎麽改,每次換盤後,一更新FileListBox.directory,出錯信 息依舊。最後我想了個最直接的方法:只放一個FileListBox和一個Edit元件,同樣的 換盤順序,哈!同樣的錯誤資訊再次出現。看看Delphi的根源程式吧: -- I:\Program Files\Borland\Delphi 3\Source\VCL\filectrl.pas中: procedure TFileListBox.SetDirectory(const NewDirectory: string); begin if AnsiCompareFileName(NewDirectory, FDirectory) <> 0 then begin { go to old directory first, in case not complete pathname and curdir changed - probably not necessary } ChDir(FDirectory); // 哼!就是這兒,害得我好慘。 ChDir(NewDirectory); { exception raised if invalid dir } GetDir(0, FDirectory); { store correct directory name } ReadFileNames; end; end; 唉,連Delphi先生都說:“可能不需要”(probably not necessary)。 而實際上,我在修改了這裏之後,仍然不對. 我又發現,在filectrl.pas中,有好幾處這樣 的地方需要修改. 最後,我只得放棄用FileListBox,改用ListBox了. 唉! 98-6-17 1:12 ExtractAssociatedIcon()和ExtractIcon() 可從指定文件中分離出其icon 或其相關程式的icon. // Delphi 3 // uses ..., ShellAPI; procedure TForm1.Button1Click(Sender: TObject); var FileName: AnsiString; begin FileName := 'd:\temp\Project1.exe'; Image1.Picture.Icon.Handle := ExtractIcon(Hinstance, pchar(FileName), 0); end; 98-6-17 1:01 Lloyd's help file (ldelphi.zip) 錢達智兄推薦的技術文件。 TrayIcon.zip 同樣是達智兄推薦的一個協助將您的程式放到開始功能列的右下角的元件。 98-6-13 2:36 string和pchar的相互轉換: string --> pchar: pchar(str:string); pchar --> string: strpas(p:pchar); 98-6-12 18:02 關於IOResult 唉!雖然我喜歡Delphi,可也不希望有一個個的bug出現! procedure TForm1.FormCreate(Sender: TObject); begin {$i-} chdir('dsafadsf'); chdir('.'); {$i } showmessage(inttohex(ioresult,4)); showmessage(inttohex(ioresult,4)); end; 請看這個過程:自己作一下,你會發現,兩個Showmessage的結果竟然不一樣! --= 98-6-18 11:03 =-- Sorry, 我錯怪Delphi了. 事實上, 在Delphi中, 當設爲{$i-}之後, 如果 發生了I/O錯誤, 一定要調用IOResult來清除這一錯誤代碼.(見聯機幫助) (愛之深,恨之切嘛. xixi) 98-6-10 14:53 給陣列直接賦值的方法: ArrayTest: array[1..2, 1..2] of integer = ((1, 2), (3, 4)); 變數命名法:(這種前置小寫變數類型的做法挺好) iRecord: integer; recRead: TTest; -----------------《DELPHI新聞組學習筆記》--------------- 這類字串函數(像是PadR,PadL)自己練習寫寫看其實挺有趣的;如果急著要用,類似這樣子的字串處 理函數在網路上不少,如Delphi 2.0 深度曆險就有個叫做 XProc 的檔案,裏頭就有很多。 幸好我這裏有 cj.sor..., 以後有這種問題時,請告訴大家 cj.sor . boshiamy.sor. phone.sor 可以 從哪里取得,這樣,有心幫忙的朋友好幫忙測試。 -----------------《DELPHI新聞組學習筆記》--------------- (cj.sor是什麽?) 98-6-9 22:55 作了一個滑鼠拖放的編程。發現有一個地方有點容易弄錯,那就是在 OnDragOver事件中,一定要顯式地指定Accept的值。 procedure TMainForm.DescListBoxDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); begin if (Source=FileListBox) and (fileexists(FileListBox.FileName)) then accept:=true; end; 這是錯的。只有在then子句後加入 else accept:=false; 才能得到正確的結果。當然,還有一個更簡單的寫法,只要一行: accept:=(Source=FileListBox) and (fileexists(FileListBox.FileName)); 98-6-8 22:29 今天看到了《DELPHI新聞組學習筆記》,不錯,現摘抄一例: 11 How To Hide TaskBar Of Win95? 怎樣隱藏Win95 的任務欄? 回答 First call the Windows API function FindWindow() to retrieve the handle to the TaskBar Window, then call the Windows API function ShowWindow() passing the predefined constant SW_HIDE. Example: procedure TForm1.Button1Click(Sender: TObject); var hTaskBar : THandle; begin hTaskbar := FindWindow('Shell_TrayWnd', Nil); ShowWindow(hTaskBar, SW_HIDE); end; procedure TForm1.Button2Click(Sender: TObject); var hTaskBar : THandle; begin hTaskbar := FindWindow('Shell_TrayWnd', Nil); ShowWindow(hTaskBar, SW_SHOWNORMAL); end; (歸根到底,還是使用了Windows API。) 關於Win95快捷方式的API函數:IShellLink 詳情可從Win32 Programmer's Reference中查到。值得一提的是: Resolve 在必要時候對IShellLink進行刷新 GetWorkingDirectory 取得IShellLink的工作目錄 98-6-8 3:19 我發現了Delphi的一個小的問題: 在Delphi的原班函數和 Win32 Api 中,各有一個函數爲closefind。當uses子句中 包含windows時,closefind便自動使用Win32 Api的說明。如 FindClose(SearchRec); 只好改爲 FindClose(SearchRec.findhandle); 不知有無更好的方法。:( --= 98-8-8 =-- 找到了! 用 Sysutils.FindClose(SearchRec); 函數findfirst和findnext的通用常式 Found := FindFirst(Path, Attr, SearchRec); while Found = 0 do begin ProcessSearchRec(SearchRec); Found := FindNext(SearchRec); end; FindClose(SearchRec); 98-6-8 1:31 exit用在主程序中會中止程式;用在過程中則會單純地退出這個過程。 這本是個簡單的常識,我卻到現在才會...... 98-6-7 23:31 保留字Initialization和finalization 在一個Form的源代碼的結束行的標誌"end."前,可以加上如下兩個保留字 initialization { 在這裏你可以對資料進行初始化 } finalization { 這裏你可以做一些善後工作,如釋放記憶體 } end. 98-6-6 1:55 GetVolumeInformation函數及其幫助文件的小錯誤 函數GetVolumeInformation可以取得指定盤符的文件系統類型和其他一些重要參數 BOOL GetVolumeInformation( LPCTSTR lpRootPathName, // address of root directory of the file system LPTSTR lpVolumeNameBuffer, // address of name of the volume DWORD nVolumeNameSize, // length of lpVolumeNameBuffer LPDWORD lpVolumeSerialNumber, // address of volume serial number LPDWORD lpMaximumComponentLength, // address of system's maximum filename length LPDWORD lpFileSystemFlags, // address of file system flags LPTSTR lpFileSystemNameBuffer, // address of name of file system DWORD nFileSystemNameSize // length of lpFileSystemNameBuffer ); 這是在Win32API的Help文件中的說明,可惜有些錯誤,那就是最後兩個LPDWORD,應爲DWORD才對。 98-6-5 14:38 demos/doc/filmanex/fmxutils.pas有一處bug 98-5-31 3:07. 看了demos/teechart中的常式,哇!功能太全太多了。 chat* lov teechart 號外號外,文安小生和teechart相愛了! 98.5.29 我找了許久,並在無意中發現的--有關String類型的另兩個函數/過程 procedure SetLength(var S: string; NewLength: Integer); function Length(S: string): Integer; //Length returns the number of characters used in a string. chat* ah 98.5.25 string的相關過程和函數(省得以後到處找:) The SysUtils unit provides a number of null-terminated string handling functions. The following table gives a brief description of each of these functions. -------- ----------- Function Description -------- ----------- StrAlloc Allocates a character buffer of a given size on the heap. StrBufSize Returns the size of a character buffer allocated using StrAlloc or StrNew. StrCat Concatenates two strings. StrComp Compares two strings. StrCopy Copies a string. StrDispose Disposes a character buffer allocated using StrAlloc or StrNew. StrECopy Copies a string and returns a pointer to the end of the string. StrEnd Returns a pointer to the end of a string. StrFmt Formats one or more values into a string. StrIComp Compares two strings without case sensitivity. StrLCat Concatenates two strings with a given maximum length of the resulting string. StrLComp Compares two strings for a given maximum length. StrLCopy Copies a string up to a given maximum length. StrLen Returns the length of a string. StrLFmt Formats one or more values into a string with a given maximum length. StrLIComp Compares two strings for a given maximum length without case sensitivity. StrLower Converts a string to lowercase. StrMove Moves a block of characters from one string to another. StrNew Allocates a string on the heap. StrPCopy Copies a Pascal string to a null-terminated string. StrPLCopy Copies a Pascal string to a null-terminated string with a given maximum length. StrPos Returns a pointer to the first occurrence of a given substring within a string. StrRScan Returns a pointer to the last occurrence of a given character within a string. StrScan Returns a pointer to the first occurrence of a given character within a string. StrUpper Converts a string to uppercase. 命令行參數的使用 Delphi提供了訪問命令行參數的方便的方式,那就是使用 ParamStr和ParamCount函數。其中ParamStr(0)返回的是當 前程式名,如C:\TEST\MYPROG.EXE,ParamStr(1)返回第一 個參數,以此類推;ParamCount則是參數個數。示例如下 var I: Word; Y: Integer; begin Y := 10; for I := 1 to ParamCount do begin Canvas.TextOut(5, Y, ParamStr(I)); Y := Y Canvas.TextHeight(ParamStr(I)) 5; end; end; 修改系統時間時應注意的問題 一開始,我使用GetSystemTime和SetSystemTime,但發現結果不對, 經仔細檢查才知道,這中間的誤差是8個小時,正好是中國的時區數。 改用GetLocalTime和SetLocalTime後,一切正常。 心得02 98-7-20 1:09 怎樣設置一個Form的長寬的最大和最小值(從D201tech.hlp翻譯) 在開始加入: TForm1 = class(TForm) private { Private declarations } procedure WMGetMinMaxInfo(var MSG: Tmessage); message WM_GetMinMaxInfo; ... 然後: procedure TForm1.WMGetMinMaxInfo(var MSG: Tmessage); Begin inherited; with PMinMaxInfo(MSG.lparam)^ do begin with ptMinTrackSize do begin X := 300; Y := 150; end; with ptMaxTrackSize do begin X := 350; Y := 250; end; end; end; 98-7-18 16:21 看了以前從網上下載的Tipexplr.zip。顧名思義,這是一個Delphi的Tips的管理 軟體。帶全部源碼,才58K。它本身帶有50個左右的很有用的小技巧,分成16大類,每個 條目都很好查。更妙的是,你可以動態更新Tips資料庫。哎呀,我從前怎麽沒注意呢? 98-7-18 0:27 見到7月13日的《電腦報》上,有廣西黃慧強的文章《在Delphi中支援文件拖放的程式》 試了一下,真的很好。突然很想知道他從什麽地方學到的這些專業技巧。 unit drag_support_demo; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,shellapi, StdCtrls; type TForm1 = class(TForm) Memo1: TMemo; procedure FormCreate(Sender: TObject); private { Private declarations } public { Public declarations } procedure wmdropfiles(var message:tmessage);message wm_dropfiles; end; var Form1: TForm1; implementation {$R *.DFM} procedure TForm1.FormCreate(Sender: TObject); begin Dragacceptfiles(form1.handle,true); end; procedure tform1.wmdropfiles(var message:tmessage); var p:array[0..254] of char; i:word; begin inherited; memo1.lines.clear; {$IFDEF WIN32} I:=dragqueryfile(message.wparam,$ffffffff,nil,0); {$ELSE} I:=dragqueryfile(message.wparam,$ffff,nil,0); {$ENDIF} caption:=inttostr(i); for i:=0 to i-1 do begin dragqueryfile(message.wparam,i,p,255); memo1.lines.add(strpas(p)); end; end; end. 98-7-17 18:05 剛才看到《電腦報》上的一篇文章, 差點暈過去。題目是《用Delphi實現超連結》,是上海的汪箴 先生的。請看我7月3日的筆記:恰好比電腦報發表日期早10天。真不知是不是他......也許是我太多 心了?但不管怎麽說,我很想也完全有資格發表這篇文章。要不,我有了好的主意,不把它先放在網 上,先投稿,等發表再說? 98-7-17 8:1 昨晚輕鬆地把GameMenu搞定了(見“我的作品”)。這個程式的主要思路是: 1.使用SystemParametersInfo()的SPI_SETSCREENSAVEACTIVE參數,使程式不回應Win95。 2.用HideTray和ShowTray過程,隱藏任務條。 3.程式運行時,最大化視窗,無標題。 4.提供加密存放的口令保護。 5.有運行日誌功能。 這樣,使用者就無法在程式運行的過程中,輕易地中止、切換程式,或是通過開始功能表運行其他程式。 另外,程式中還用到其他的一些小技巧。如有人需要源碼,請發email。歡迎在信中簡要介紹一下自己 :) 98-7-15 14:48 朋友找我做個小程式,要求只在win95中顯示一個遊戲功能表,別的程式通通不能調用,也不能啟動開始 功能表。我記得見過一篇文章,大概是用SystemParametersInfo(),反正准能查到,就一口答應了。在 Win32API聯機幫助裏查到SPI_SETSCREENSAVEACTIVE參數,可怎麽做都是不行.終於找到<電腦報>的這 篇文章,是上海的汪箴朋友的.原來要用SCREENSAVERRUNNING參數!要命的是,在幫助文件裏沒有! 唉,Delphi的幫助文件確實是錯漏很多,... 附,具體實現方法:(我把原文的方法做了一點改進,詳見<電腦報>6月8日"軟體世界") 設置: systemparametersinfo(spi_screensaverrunning,1,nil,0); 取消: systemparametersinfo(spi_screensaverrunning,0,nil,0); 98-7-13 23:51 上大學時曾學過Pascal,但很快就忘光了;既然要學好Delphi,那就再補習一下吧. 字串處理函數 copy(str,pos,num) 從str字串的pos處開始,截取num個字元的串返回. 假設str爲'abcdef',copy(str,3,2)='cd',copy(str,4,10)='def' concat(str1,str2{,strn}) 把各引數連接起來,返回連接後的字串(長度不能超過255) length(str) 返回str的字元個數,即其長度. pos(obj,target) 在target字串中找出第一個出現obj的第一個字元位置,如果找不到,返回0. 數學函數 abs(x) 絕對值 arctan(x) 反正切 cos(x) exp(x) e的x次冪 frac(x) 取小數部分 int(x) 取整 ln(x) 自然對數 sin(x) sqr(x) x*x sqrt(x) 平方根 其他 pred(x) pred('D')='C', pred(true)=1; succ(x) succ('Y')='Z', succ(pred(x))=x ord(x) 求x在字元集中的序號,如ord('A')=65 chr(x) chr(65)='A' round(x) 四捨五入 trunc(x) trunc(4.8)=4,trunc('-3.6')=-3 upcase(x) upcase('a')='A' hi(I) hi($2A30)=$2A lo(I) lo($2A30)=$30 random(n) 産生[0,n)間的隨機整數 sizeof(name) 求出某類型或變數在記憶體中佔用的位元組數 swap(num) swap($3621)=$2136 98-7-13 23:51 加密/解密一個字串(摘自D201tech.hlp) { Begin code } program Crypt; uses WinCRT; const C1 = 52845; C2 = 22719; function Encrypt(const S: String; Key: Word): String; var I: byte; begin Result[0] := S[0]; for I := 1 to Length(S) do begin Result[I] := char(byte(S[I]) xor (Key shr 8)); Key := (byte(Result[I]) Key) * C1 C2; end; end; function Decrypt(const S: String; Key: Word): String; var I: byte; begin Result[0] := S[0]; for I := 1 to Length(S) do begin Result[I] := char(byte(S[I]) xor (Key shr 8)); Key := (byte(S[I]) Key) * C1 C2; end; end; var S: string; begin Write('>'); ReadLn(S); S := Encrypt(S,12345); WriteLn(S); S := Decrypt(S,12345); WriteLn(S); end. 98-7-3 11:49 真是太丟人了.我犯了一個簡單的錯誤,竟然用了好長時間才找出.但我想也許會有 別的朋友也會遇到,不妨把它寫下. 事情是這樣的:從昨天下午,我發現Delphi中按CTRL-F查找時,不論輸入什麽,總是 有錯誤提示 Tried to search marked block but it is invalid. 我想,有可能這兩天安裝某軟體,造成系統文件不一致.於是我重新安裝了一遍Delphi. 還是照舊.於是我進入純MSDOS方式,鍵入命令 copy \windows\sysbckup\*.dll \windows\system 也不行.又打開Delphi的所有有關選項設置的對話方塊,也沒找到有相關的資訊.最後, 我想,是不是就在Find對話方塊中?再次Find,看到對話方塊裏的Scope組中不知何時選了 selected text,(難怪!)改成Global,按OK.真相大白. 98-7-2 21:02 在程式中調用瀏覽器 一直很羡慕別人能在程式中加入一個有主頁地址的Label,點它會直接進入Win95 的缺省瀏覽器。“這裏面用了什麽高級系統調用呢?”想啊想啊...... 你有沒有聽說過“精誠所至,金石爲開”?我就是。因爲我終於想到了!請看: 1、在Form上放一個Label1,Caption設爲一個URL,如 http://afg.yeah.net 在Font選項中選中下劃線。 2、雙擊它,進入onClick事件。加上: ShellExecute(Handle, nil,pchar(Label1.caption),'','', 0); 3、在程式開頭部份的uses子句中加上 shellapi。 運行。怎麽樣?感覺很好吧。另外,如果想調用Email程式也很簡單,只要這樣寫 mailto:afg@163.net 就搞定了。至於其他Internet服務如ftp,telnet,gopher,news...應該同樣道理吧。 98-7-1 21:41 今天上傳了rxlib.zip。別小看它,我認爲這是一個相當好而全的元件庫。 因主頁空間有限,只好刪除……安裝步驟如下:(我只在Delphi3.0下安裝過) 1、解壓至一個新的子目錄中,運行rxinst.exe,此後會自動安裝在delphi 3\rx下。 2、將rx\units下的Rxctl.dpl,Rxdb.dpl,Rxtools.dpl拷貝到windows\system目錄。 3、在功能表"File\Open..."下打開Rxctl.dpk,選Compile.用同樣方法compile另兩個 文件Rxdb.dpk和Rxtools.dpk. 4、打開Dclrxctl.dpk,單擊Install按鈕。經過幾秒鐘後,Delphi提示:已正確安 裝如下元件:...... 5、如法安裝Dclrxdb.dpk,Dclrxtls.dpk。 好了,看一下VCL元件工具條的最右邊,已經多了RX Controls,RX DBAware,RX tools 三組共58種功能強大的元件,夠爽吧?用一下看。(遺憾的是只有俄文的說明。) 98-7-1 10:10 FileGetAttr函數的注意事項 FileGetAttr(FileName)返回filename指定的文件的屬性.在Delphi的Demo fmxutils.pas裏有這樣一個實用函數: function HasAttr(const FileName: string; Attr: Word): Boolean; begin Result := (FileGetAttr(FileName) and Attr) = Attr; end; 但我在實際使用中,卻得到了錯誤的結果:當filename不存在時,result恒大於0! 這是因爲FileGetAttr在遇到一個錯誤時,會返回-1,而-1即$FFFF,或$FFFFFFFF, 和任意非0值相與,當然都會大於0了. 98-6-30 23:43 Vitual Key 鍵值列表 如果你要編寫OnKeyDown一類的過程,那就一定用得著它。 98-8-12 9:15 今天我發現, 這裏的列表並不全; 真正全的在Windows.pas裏。仔細一看,裏面 好東西多多:有Windows錯誤代碼的簡要說明,還有各類紙張的名稱、大小…… 所有和windows有關的常量的定義和注釋都能在裏面找得到,有些還有用ASCII 碼畫的表格呢! 98-6-30 23:32 如何自動註冊(login)一個有口令保護的Paradox表? 首先,這個table的屬性必須爲false(否則在一開始就會提示輸入口令),然後 把這兩條指令放入form的onCreate中去: Session.AddPassword('My secret password'); Table1.Active := True; 關閉這個table時,可以用下面命令清除口令 RemovePassword('My secret password'); 或用這條命令清除所有口令 RemoveAllPasswords; (注:以上均只對Paradox適用) 98-6-30 23:24 運行中拖動一個元件(翻譯) 在一個新的Form中放入一個Panel,加入如下代碼: procedure TForm1.Panel1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); const SC_DragMove = $F012; { a magic number } begin ReleaseCapture; panel1.perform(WM_SysCommand, SC_DragMove, 0); end; 運行,你當然知道這時應該拖動它。怎麽樣?Delphi真是神奇。 98-6-30 1:35 StatusLine在運行時竟然可以通過滑鼠拖動改變大小! 通過設置SizeGrip爲true(這也是投省值)來實現。真有趣。利用這個特性, 可以用在開發中,實現一些有用的功能。 98-6-28 21:58 幾個新函數EncodeDate,Assigned EncodeDate(Year, Month, Day: Word): TDateTime; 給定year,month,day,這個函數可以返回一個TDateTime類型。 相關函數:DateToStr,EncodeTime,DecodeDate。 Assigned(p:pointer):boolean; 如果p爲nil,返回false;否則返回true.但它無法判斷p是否一個合法的指標。 示例: var P: Pointer; begin P := nil; if Assigned (P) then Writeln ('You won''t see this'); GetMem(P, 1024); {P valid} FreeMem(P, 1024); {P no longer valid and still not nil} if Assigned (P) then Writeln ('You''ll see this'); end; 98-6-26 22:13 今晚在瀏覽Delphi的Online Help時,又發現了兩個很好用的內部函數: High()和Low() 先說High:High(X)函數返回參數的取值範圍內的最大值,其類型爲X,或X的 索引。X既可以是一個類型標識,也可以是一個變數,其類型必須爲下面之一: 變數類型 High(X)的返回值 ------------------------------------------- 序數類型 這一類型的最高取值 陣列類型 陣列索引的最大值 字串類型 這一字串聲明過的長度 動態陣列 返回實際元素個數的負值 字串參數 返回實際元素個數的負值 示例: function Sum( var X: array of Double): Double; var I: Word; S: Double; begin S := 0; { Note that open array index range is always zero-based. } for I := 0 to High(X) do S := S X[I]; Sum := S; end; Low(X)的含義可以參考上面的描述,但正好相反。 98-6-25 0:52 TBitmap.Transparent和TransparentColor 在查看Delphi的Help時發現,設置TBitmap.Transparent爲true,再適當設置 TBitmap.TransparentColor,可做出具有透明效果的Bitmap來。 98-6-24 23:22 今天看到一張光碟上有不少Delphi的技術文件,其中有一個是D201tech.hlp, 顧名思義,是關於Delphi2.01的。打開一看,竟有許多對我而言非常有用的條 目。如“自動連接Paradox資料庫”,“virtual key鍵值列表”,“從BLOB字 段中取得Bitmap”,“加密/解密字串”,“使用Bitmap做爲FORM的背景”, “利用後臺線程優化資料庫查詢”......太好了。我打算把它放在“技術文檔” 中,供朋友們下載。有時間的話,也會有選擇地翻譯幾個,給英語不太好的朋 友提供一些方便。:) 心得03 98-8-23 22:00 raise的用法 看Demo時學的: raise Exception.Create('Project ID is required'); 在工程文件中Application.Run語句之前加入下面語句,可不讓主Form在運行時顯示: Application.ShowMainForm := False; 在CSDemos.dpr中,有許多有用的c/s編程技巧…… 98-8-23 21:40 在Delphi代碼中定義資料庫 近來由於應用上的需要,要在運行中動態生成資料庫,結構不定。我想一定要用 BDE32API中的知識才能實現。無意中在5月7日的《中國電腦報》上發現一篇文 章《在Delphi代碼中定義資料庫》,幫了我的大忙。部分代碼如下: procedure tform1.create_tbl; var tbl:ttable; begin tbl:=ttable.create(self); // 如沒有聲明中的"tform1.",Delphi不認這個self with tbl do begin datebasename:=;dbdemos'; tablename:='my_tbl'; with fielddefs do begin clear; add('No',ftInteger,0,false); add('Name',ftString,0,false); ... end; with indexdefs do begin clear; add('primary','no',[ixPrimary,ixUnique]); ... end; CreateTable; end; end; 98-8-20 22:24 異種資料庫之間的互相轉換 記得過去曾經見到過一篇文章,介紹如何用一極簡單的方法將異種資料庫之間 的表(Table)相互轉化,但沒有記住作者是用了什麽方法。現在,我需要有這 樣一種工具,怎麽也找不到,只能用笨辦法,一條記錄一條記錄地Insert。好 在剛剛在看Help文件時找到了要找的:那就是用TBatchMove!真是的,天天都 在我眼皮底下晃,爲什麽到現在才發現…… 有個Demo工程在Delphi 3\HELP\EXAMPLES\BATCHMV之下,功能很全的。 98-8-20 22:22 在程式運行一耗時操作時改變滑鼠形狀 begin screen.cursor:=crHourglass; try ... // do some long-time work finally screen.cursor:=crDefault; end; end; 1998-08-19 11:03 在TQuery中查詢時關鍵字衝突 我用了這樣一個查詢: select no,name,py,belong from dwbm 結果Delphi提示"Invalid use of keyword...",換成 select "no",name,py,belong from dwbm 查詢結果的第一列又恒爲 "no",經反復試驗,最後終於成功了: select "a"."no",name,py,belong from dwbm a 1998-08-18 14:06 我的第一篇Delphi文章《Delphi使用技巧四則》 請看 http://www.ciw.com.cn/ciw/751/d0902.htm 這是中國電腦報的站點。 98-8-15 20:56 InsertRecord和AppendRecord的一條注意事項 在用InsertRecord插入一條記錄時,發現有兩個欄位顛倒了。又核對了一 遍資料庫(table)中的欄位順序,沒有發現不一致的地方。想起用了Field Editor,會不會是……打開Field Editor,果然,爲了顯示的需要,我把 其中兩個欄位對調了位置。原來,InsertRecord中的欄位順序應該與Field Editor中的順序一致才行。這一點,好象書上和聯機幫助上都沒有提到過。 這一點,對AppendRecord也同樣。 98-8-12 21:44 一夜之間 昨天朋友找我幫忙,編制一個資料庫應用軟體,必須在今天早上之前完成。 我答應了,因爲我知道Delphi的能力,也瞭解到這個應用並不是多麽複 雜。結果,從晚8點到晚0點,程式順利作成,而且沒有忘記加了個About 版權資訊對話方塊和一個Splash啓動封面。連我也從來沒有想到過一夜之 間做好一個介面漂亮功能齊全的軟體! 記
------
**********************************************************
哈哈&兵燹
最會的2大絕招 這個不會與那個也不會 哈哈哈 粉好

Delphi K.Top的K.Top分兩個字解釋Top代表尖端的意思,希望本討論區能提供Delphi的尖端新知
K.表Knowlege 知識,就是本站的標語:Open our mind
系統時間:2024-04-28 16:24:04
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!