001期電子報編輯中心 |
|
bruce0211
版主 ![]() ![]() ![]() ![]() ![]() 發表:157 回覆:668 積分:279 註冊:2002-06-13 發送簡訊給我 |
【文章】目錄處理函式三則:_DelTree(),_XCopy(),_Move()
【作者】源碼任務 bruce0211@yahoo.com.tw 2003/11/25
【內文】常用目錄處理函式整理 for BCB/Delphi ■ 用法
參數位置同 DOS 公用程式 , 沒用到什麼特殊 API , 應該適用於各種 BCB/Delphi 版本 _DelTree() 刪除整個目錄(含子目錄)
_XCopy() 複製整個目錄(含子目錄)
_Move() 搬移整個目錄(含子目錄) ■ BCB 版本
private: // User declarations void __fastcall _XCopy(String ASourceDir,String ADestDir); void __fastcall _Move(String ASourceDir,String ADestDir); void __fastcall _DelTree(String ASourceDir); //--------------------------------------------------------------------------- void __fastcall TForm1::_XCopy(String ASourceDir,String ADestDir) { TSearchRec SearchRec; String Sour=ASourceDir; String Dest=ADestDir; if (Sour.SubString(Sour.Length(),1)!="\\") Sour=Sour "\\"; if (Dest.SubString(Dest.Length(),1)!="\\") Dest=Dest "\\"; if (!DirectoryExists(ASourceDir)) // 要 #include "FileCtrl.hpp" 才有這個函式 { ShowMessage("來源目錄不存在!!"); return; } if (!DirectoryExists(ADestDir)) ForceDirectories(ADestDir); if (FindFirst(Sour "*.*", faAnyFile, SearchRec) == 0) { do { //應該可用 if ((SearchRec.Attr & faDirectory) != 0) 取代下面的判斷 if ( (SearchRec.Attr == (faDirectory)) || (SearchRec.Attr == (faDirectory | faArchive)) || (SearchRec.Attr == (faDirectory | faReadOnly)) || (SearchRec.Attr == (faDirectory | faHidden)) ) { if ((SearchRec.Name!=".") && (SearchRec.Name!="..")) { _XCopy(Sour SearchRec.Name,Dest SearchRec.Name); //遞迴呼叫 } } else { CopyFile(((String)(Sour SearchRec.Name)).c_str(),((String)(Dest SearchRec.Name)).c_str(),false); } } while (FindNext(SearchRec) == 0); FindClose(SearchRec); } } //--------------------------------------------------------------------------- void __fastcall TForm1::_Move(String ASourceDir,String ADestDir) { TSearchRec SearchRec; String Sour=ASourceDir; String Dest=ADestDir; if (Sour.SubString(Sour.Length(),1)!="\\") Sour=Sour "\\"; if (Dest.SubString(Dest.Length(),1)!="\\") Dest=Dest "\\"; if (!DirectoryExists(ASourceDir)) // 要 #include "FileCtrl.hpp" 才有這個函式 { ShowMessage("來源目錄不存在!!"); return; } if (!DirectoryExists(ADestDir)) ForceDirectories(ADestDir); if (FindFirst(Sour "*.*", faAnyFile, SearchRec) == 0) { do { //應該可用 if ((SearchRec.Attr & faDirectory) != 0) 取代下面的判斷 if ( (SearchRec.Attr == (faDirectory)) || (SearchRec.Attr == (faDirectory | faArchive)) || (SearchRec.Attr == (faDirectory | faReadOnly)) || (SearchRec.Attr == (faDirectory | faHidden)) ) { if ((SearchRec.Name!=".") && (SearchRec.Name!="..")) { _XCopy(Sour SearchRec.Name,Dest SearchRec.Name); //遞迴呼叫 _DelTree(Sour SearchRec.Name); FileSetAttr(Sour SearchRec.Name,faArchive); RemoveDir(Sour SearchRec.Name); } } else { CopyFile(((String)(Sour SearchRec.Name)).c_str(),((String)(Dest SearchRec.Name)).c_str(),false); FileSetAttr(Sour SearchRec.Name,faArchive); DeleteFile(Sour SearchRec.Name); } } while (FindNext(SearchRec) == 0); FindClose(SearchRec); } FileSetAttr(Sour,faArchive); RemoveDir(Sour); } //--------------------------------------------------------------------------- void __fastcall TForm1::_DelTree(String ASourceDir) { TSearchRec SearchRec; String Sour=ASourceDir; if (Sour.SubString(Sour.Length(),1)!="\\") Sour=Sour "\\"; if (!DirectoryExists(Sour)) // 要 #include "FileCtrl.hpp" 才有這個函式 { ShowMessage("來源目錄不存在!!"); return; } if (FindFirst(Sour "*.*", faAnyFile, SearchRec) == 0) { do { //應該可用 if ((SearchRec.Attr & faDirectory) != 0) 取代下面的判斷 if ( (SearchRec.Attr == (faDirectory)) || (SearchRec.Attr == (faDirectory | faArchive)) || (SearchRec.Attr == (faDirectory | faReadOnly)) || (SearchRec.Attr == (faDirectory | faHidden)) ) { if ((SearchRec.Name!=".") && (SearchRec.Name!="..")) { _DelTree(Sour SearchRec.Name); //遞迴呼叫 FileSetAttr(Sour SearchRec.Name,faArchive); RemoveDir(Sour SearchRec.Name); } } else { FileSetAttr(Sour SearchRec.Name,faArchive); DeleteFile(Sour SearchRec.Name); } } while (FindNext(SearchRec) == 0); FindClose(SearchRec); } FileSetAttr(Sour,faArchive); RemoveDir(Sour); }■ Delphi 版本 private { Private declarations } procedure _XCopy(ASourceDir:String; ADestDir:String); procedure _Move(ASourceDir:String; ADestDir:String); procedure _DelTree(ASourceDir:String); //--------------------------------------------------------------------------- procedure TForm1._XCopy(ASourceDir:String; ADestDir:String); var FileRec:TSearchrec; Sour:String; Dest:String; begin Sour:=ASourceDir; Dest:=ADestDir; if Sour[Length(Sour)]<>'\' then Sour := Sour '\'; if Dest[Length(Dest)]<>'\' then Dest := Dest '\'; if not DirectoryExists(ASourceDir) then begin ShowMessage('來源目錄不存在!!'); exit; end; if not DirectoryExists(ADestDir) then begin ForceDirectories(ADestDir); end; if FindFirst(Sour '*.*',faAnyfile,FileRec) = 0 then repeat if ((FileRec.Attr and faDirectory) <> 0) then begin if (FileRec.Name<>'.') and (FileRec.Name<>'..') then begin _XCopy(Sour FileRec.Name,Dest FileRec.Name); end; end else begin CopyFile(PChar(Sour FileRec.Name),PChar(Dest FileRec.Name),false); end; until FindNext(FileRec)<>0; FindClose(FileRec); end; //--------------------------------------------------------------------------- procedure TForm1._Move(ASourceDir:String; ADestDir:String); var FileRec:TSearchrec; Sour:String; Dest:String; begin Sour:=ASourceDir; Dest:=ADestDir; if Sour[Length(Sour)]<>'\' then Sour := Sour '\'; if Dest[Length(Dest)]<>'\' then Dest := Dest '\'; if not DirectoryExists(ASourceDir) then begin ShowMessage('來源目錄不存在!!'); exit; end; if not DirectoryExists(ADestDir) then begin ForceDirectories(ADestDir); end; if FindFirst(Sour '*.*',faAnyfile,FileRec) = 0 then repeat if ((FileRec.Attr and faDirectory) <> 0) then begin if (FileRec.Name<>'.') and (FileRec.Name<>'..') then begin _XCopy(Sour FileRec.Name,Dest FileRec.Name); _DelTree(Sour FileRec.Name); FileSetAttr(Sour FileRec.Name,faArchive); RemoveDir(Sour FileRec.Name); end; end else begin CopyFile(PChar(Sour FileRec.Name),PChar(Dest FileRec.Name),false); FileSetAttr(Sour FileRec.Name,faArchive); deletefile(Sour FileRec.Name); end; until FindNext(FileRec)<>0; FindClose(FileRec); FileSetAttr(Sour,faArchive); RemoveDir(Sour); end; //--------------------------------------------------------------------------- procedure TForm1._DelTree(ASourceDir:String); var FileRec:TSearchrec; Sour:String; begin Sour:=ASourceDir; if Sour[Length(Sour)]<>'\' then Sour := Sour '\'; if not DirectoryExists(ASourceDir) then begin ShowMessage('來源目錄不存在!!'); exit; end; if FindFirst(Sour '*.*',faAnyfile,FileRec) = 0 then repeat //if (FileRec.Attr = faDirectory) then if ((FileRec.Attr and faDirectory) <> 0) then begin if (FileRec.Name<>'.') and (FileRec.Name<>'..') then begin _DelTree(Sour FileRec.Name); FileSetAttr(Sour FileRec.Name,faArchive); RemoveDir(Sour FileRec.Name); end; end else begin FileSetAttr(Sour FileRec.Name,faArchive); deletefile(Sour FileRec.Name); end; until FindNext(FileRec)<>0; FindClose(FileRec); FileSetAttr(Sour,faArchive); RemoveDir(Sour); end; |
bruce0211
版主 ![]() ![]() ![]() ![]() ![]() 發表:157 回覆:668 積分:279 註冊:2002-06-13 發送簡訊給我 |
【文章】螢幕畫面處理函式二則:_ScreenSaveToFile(),_ScreenLoadFromFile()
【作者】源碼任務 bruce0211@yahoo.com.tw 2003/11/25
【內文】常用螢幕畫面處理函式整理 for BCB/Delphi ■ 用法
//--------------------------------------------------------------------
//函式名稱 : _ScreenSaveToFile([檔名],[存檔型態])
//函式用途 : 將螢幕畫面存檔
//參數說明 : [檔名]若為空字串 則自動給定流水號檔名 ; [存檔型態] 0:bmp 1:jpg
//函式範例 : _ScreenSaveToFile('',0); 將目前螢幕畫面存成 *.bmp 檔,檔名使用流水號
//補充說明 : 可在程式中隨時呼叫本函式 , 將多個畫面分別存檔以利式樣製作剪貼
//--------------------------------------------------------------------
//函式名稱 : _ScreenLoadFromFile([桌布檔名位置])
//函式用途 : 更換螢幕桌布
//參數說明 :
//函式範例 : _ScreenLoadFromFile('c:\test.bmp'); 將目前桌布換成 c:\test.bmp
//補充說明 :
//-------------------------------------------------------------------- ■ 注意
要先 #include "jpeg.hpp" 或 uses jpeg ■ BCB 版本
//--------------------------------------------------------------------------- void __fastcall _ScreenSaveToFile(String AFileName, int AFileType) { TJPEGImage *jpg = new TJPEGImage(); Graphics::TBitmap *bmp = new Graphics::TBitmap(); bmp->Width=Screen->Width; bmp->Height=Screen->Height; String my_filename; my_filename=Trim(AFileName); if (my_filename=="") { if (AFileType==0) my_filename="c:\\" FormatDateTime("mmdd_hhnnss_zzz",Now()) ".bmp"; //流水號檔名 else my_filename="c:\\" FormatDateTime("mmdd_hhnnss_zzz",Now()) ".jpg"; //流水號檔名 } HWND d; HDC dc; if((d=GetDesktopWindow())!=NULL) { dc=GetDC(d); BitBlt(bmp->Canvas->Handle,0,0,bmp->Width,bmp->Height,dc,0,0,SRCCOPY); ReleaseDC(d,dc); if (AFileType==0) bmp->SaveToFile(my_filename); else { jpg->Assign(bmp); jpg->SaveToFile(my_filename); } } delete jpg; delete bmp; } //--------------------------------------------------------------------------- void __fastcall _ScreenLoadFromFile(String ABmpFileName) { if (!FileExists(ABmpFileName)) return; SystemParametersInfo(SPI_SETDESKWALLPAPER, NULL, ABmpFileName.c_str(), SPIF_UPDATEINIFILE | SPIF_SENDCHANGE); }■ Delphi 版本 //--------------------------------------------------------------------------- procedure _ScreenSaveToFile(AFileName: String ; AFileType: integer); var d:HWND; dc:HDC; jpg:TJPEGImage; bmp:TBitmap; my_filename:String; begin jpg := TJPEGImage.Create; bmp := TBitmap.Create; bmp.Width:=Screen.width; bmp.Height:=Screen.height; my_filename:=Trim(AFileName); if my_filename='' then begin if AFileType=0 then my_filename:='c:\' FormatDateTime('mmdd_hhnnss_zzz',Now) '.bmp' //流水號檔名 else my_filename:='c:\' FormatDateTime('mmdd_hhnnss_zzz',Now) '.jpg' //流水號檔名 end; d:=GetDesktopWindow(); if (d<>0) then begin dc:=GetDC(d); BitBlt(bmp.Canvas.Handle,0,0,bmp.Width,bmp.Height,dc,0,0,SRCCOPY); ReleaseDC(d,dc); if AFileType=0 then begin bmp.SaveToFile(my_filename); end else begin jpg.Assign(bmp); jpg.SaveToFile(my_filename); end; end; jpg.Free; bmp.Free; end; //--------------------------------------------------------------------------- procedure _ScreenLoadFromFile(ABmpFileName:String); begin if not FileExists(ABmpFileName) then exit; SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, PChar(ABmpFileName), SPIF_UPDATEINIFILE or SPIF_SENDCHANGE); end; |
領航天使
站長 ![]() ![]() ![]() ![]() ![]() ![]() 發表:12216 回覆:4186 積分:4084 註冊:2001-07-25 發送簡訊給我 |
【文章】如何將Quick Report的報表轉成圖檔或PDF檔
【作者】hagar
【內文】來源:http://delphi.ktop.com.tw/topic.php?topic_id=40801 1.BMP
procedure TForm5.Button4Click(Sender: TObject); var BMP: TBitMap; StoredUnits: TQRUnit; i: integer; StoreDir: string; begin StoreDir:=''; {!!! Assign folder to store here (with ending '\'), leave blank to store in the .exe's folder} QuickRep1.Prepare; StoredUnits:=QuickRep1.Units; QuickRep1.Units:=Pixels; try for i:=1 to QuickRep1.QRPrinter.PageCount do begin BMP:=TBitMap.Create; try BMP.Width:=Round(QuickRep1.Page.Width); BMP.Height:=Round(QuickRep1.Page.Length); QuickRep1.QRPrinter.PageNumber:=i; BMP.Canvas.Draw(0, 0, QuickRep1.QRPrinter.Page); BMP.SaveToFile(StoreDir+'Page'+IntToStr(i)+'.bmp'); finally BMP.Free; end; end; finally QuickRep1.Units:=StoredUnits; end; end;2.PDF var AFilter: TPsQRPDFFilter; begin AFilter := TPsQRPDFFilter.Create('MyRep.pdf'); try QuickRep.Prepare; QuickRep.ExportToFilter(AFilter); finally QuickRep.QRPrinter.Free; QuickRep.QRPrinter := nil; AFilter.Free; end; end;參考資料: Save QReports pages as BMP: http://www.nsonic.de/Delphi/txt_WIS00489.htm http://groups.google.com.tw/groups?hl=zh-TW&lr=&ie=UTF-8&inlang=zh-TW&th=3293737e593a1cb0&rnum=29 http://groups.google.com.tw/groups?hl=zh-TW&lr=&ie=UTF-8&inlang=zh-TW&th=93ada631d63769a&rnum=1 其它相關 Tool 的連結: http://www.paperlessprinter.com/ http://www.leadtools.com/ http://www.wptools.de/
------
~~~Delphi K.Top討論區站長~~~ |
Ethan
版主 ![]() ![]() ![]() 發表:101 回覆:170 積分:78 註冊:2006-07-05 發送簡訊給我 |
【文章】MaxDB by MySQL 釋放使用 (一個企業級的免費資料庫軟體)
【作者】黃書逸(Ethan)
【內文】MySQL 與 SAPDB合作後首推的MaxDB 真是可怕的一個資料庫軟體,如果不與各位分享的話就太沒仁義道德了,最令人髮指的地方就是 DBM GUI,所以大家一定要安裝看看,看了之後一定會很感動的... http://delphi.ktop.com.tw/loadfile.php?TOPICID=12882467&CC=288113 以下節錄文章中的一段... MaxDB by MySQL 釋放使用 (一個企業級的免費資料庫軟體)
筆者:黃書逸 shuyi@unix.net.tw
MySQL AB 在產品線上增加了企業等級的 SAP-Certified 開放源碼資料庫
MySQL AB,目前在全球最受歡迎的開放源碼資料庫軟體,今天發佈了 MaxDB by MySQL並提供免費下載,MaxDB是一個高負荷的資料庫系統,SAP-Certified開放源碼資料庫一向以提供高效益及廣泛功能的風格被大眾所接受,MaxDB是MySQL AB旗艦型資料庫產品,現在擴展到企業市場並達到大規模的mySAP ERP環境的支援(SAP-DB http://www.sapdb.org),和其他應用軟體與需大量運算的企業規模等級的資料庫功能。
MySQL AB獲得了完成的商用權利來開發與行銷未來的 SAP DB 版本,目前在全球已經有設置SAP DB的企業約有5,000家,其中包括:Intel、DaimlerChysler(德國郵政)、Braun、Bayer、YAMAHA、Deutsche Post和TOYOTA。 MaxDB 7.5 支援所有的 SAP Solutions
第一個釋放的MaxDB版本為7.5.00.05,也就是SAP DB 7.4版,MaxDB7.5.00.05在推出前已經有廣泛的測試並被證明可以完全支援SAP solutions,另外MySQL會提供一個MySQL Proxy介面,可以讓使用者在不同平台間的MaxDB和MySQL資料庫溝通,也就是說可以在MaxDB與MySQL間做資料庫的轉換...... 學習,從分享開始^^
|
領航天使
站長 ![]() ![]() ![]() ![]() ![]() ![]() 發表:12216 回覆:4186 積分:4084 註冊:2001-07-25 發送簡訊給我 |
【文章】如何動態呼叫function or procedure
【作者】Mickey
【內文】文章來源:http://delphi.ktop.com.tw/topic.php?topic_id=40505
type TMyPorcdure = procedure (Sender: TObject) of Object; TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); Procedure P1(Sender: TObject); Procedure P2(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} { TForm1 } procedure TForm1.P1(Sender: TObject); begin showmessage('In P1 Procedure'); end; procedure TForm1.P2(Sender: TObject); begin showmessage('In P2 Procedure'); end; procedure TForm1.Button1Click(Sender: TObject); var m : TMyPorcdure; s : string; p : Pointer; begin s := 'P1'; p := MethodAddress(s); if p<>nil then begin TMethod(m).Code := p; TMethod(m).Data := Self; m(Sender); end else raise Exception.CreateFmt('Procedure %s not exists',[s]); s := 'P2'; p := MethodAddress(s); if p<>nil then begin TMethod(m).Code := p; TMethod(m).Data := Self; m(Sender); end else raise Exception.CreateFmt('Procedure %s not exists',[s]); end;相關參考資料: http://delphi.ktop.com.tw/topic.php?TOPIC_ID=39987 http://www.delphipraxis.net/post87477.html
------
~~~Delphi K.Top討論區站長~~~ |
領航天使
站長 ![]() ![]() ![]() ![]() ![]() ![]() 發表:12216 回覆:4186 積分:4084 註冊:2001-07-25 發送簡訊給我 |
【文章】使用OLE,在EXCEL中自動產生圖表、背景,並設定保護模式
【作者】wivern
【內文】文章來源:http://delphi.ktop.com.tw/topic.php?topic_id=40545
之前在站上看了許多 使用 OLE 來制作 Excel的文章,大部份都是在講如何填入資料,如何設定欄位的格式等,
小弟因工作需要,必須在excel中產生圖表,在網路上找了許多資料,也有了一些心得,
就在此拋磚引玉,提供一些小弟個人的心得,
因為站上很多如何填資料的文章,所以小弟就省略這一部份,
假設網友們已經填好資料,直接進入要產生圖表的部份,
//一開始先定義OLE會用到的變數,建立excel的物件 Variant Excel,Workbooks,Workbook,Charts,Chart,Range; Excel=CreateOleObject("Excel.Application"); Excel.OlePropertySet("Visible",true); //秀出Excel的畫面 Workbooks=Excel.OlePropertyGet("Workbooks"); Workbook=Workbooks.OleFunction("Add"); Worksheets=Workbook.OlePropertyGet("Worksheets"); Worksheet=Worksheets.OleFunction("Add"); // 新增一worksheet Worksheet.OlePropertySet("Name","test") ;// 設定worksheet 的名稱 //取得Charts的物件 Charts=Workbook.OlePropertyGet("Charts"); . . . 先把所需資料填入cell中 . . //建立一個新的圖表,這時圖表會開在一個新的sheet裡,而整個sheet就是一個圖表 //之後會把圖表放在其他的sheet裡 Chart=Charts.OleFunction("Add"); //設定圖表的格式,65是表示含有資料標記的折線圖,後面會有圖表格式的說明 Chart.OlePropertySet("ChartType",65); //選定要製作圖表的資料來源,這個例子我是要選擇excel中從cell(1,1)到cell(10,5)的資料, //此動作就好像用滑鼠把這一部份的欄位選起來一樣 Range=Worksheet.OlePropertyGet("Range", Worksheet.OlePropertyGet("Cells",1,1), Worksheet.OlePropertyGet("Cells",10,5)); //設定圖表的資料來源,xlRows表示資料是以列來做排列,如果資料是用行來排列,就用xlColumns, //如果是用xlRows,選取範圍的第一列就是x軸每一筆資料的名稱, //第一行是y軸資料的名稱,其餘的就是圖表裡的數值 Chart.OleProcedure("SetSourceData",Range,xlRows); //設定圖表的title Chart.OlePropertySet("HasTitle",(Variant)true); //先設定圖表有title String Charttitle="test chart!!"; Chart.OlePropertyGet("ChartTitle").OlePropertySet("Text",Charttitle.c_str()); //設定圖表x軸和y軸是否要秀出title和資料名稱 Chart.OlePropertyGet("Axes",1).OlePropertySet("HasTitle",(Variant)true); //設定x軸是否要顯示資料名稱 Chart.OlePropertyGet("Axes",1).OlePropertyGet("AxisTitle").OlePropertySet("Text","時間");//設定x軸的title Chart.OlePropertyGet("Axes",2).OlePropertySet("HasTitle",(Variant)true); //設定y軸是否要顯示資料名稱 Chart.OlePropertyGet("Axes",2).OlePropertyGet("AxisTitle").OlePropertySet("Text","次數");//設定y軸的title //設定圖表要放在哪一個sheet裡 Chart.OleProcedure("Location",2,Worksheet.OlePropertyGet("Name")); //設定圖表的位置與長寬, //Worksheet.OlePropertyGet("ChartObjects",1)表示是要設定這個sheet中第一個圖表, //如要設定第二個圖表就用Worksheet.OlePropertyGet("ChartObjects",2), //圖表的順序依在sheet中產生或放置的先後排列 Worksheet.OlePropertyGet("ChartObjects",1).OlePropertySet("Top",15); Worksheet.OlePropertyGet("ChartObjects",1).OlePropertySet("Left",20); Worksheet.OlePropertyGet("ChartObjects",1).OlePropertyGet("Width",50); Worksheet.OlePropertyGet("ChartObjects",1).OlePropertyGet("Height",30); //此時圖表已經漂漂亮亮的在sheet中囉!底下列出圖表格式常數的定義: typedef enum XlChartType { xlColumnClustered = 51, xlColumnStacked = 52, xlColumnStacked100 = 53, xl3DColumnClustered = 54, xl3DColumnStacked = 55, xl3DColumnStacked100 = 56, xlBarClustered = 57, xlBarStacked = 58, xlBarStacked100 = 59, xl3DBarClustered = 60, xl3DBarStacked = 61, xl3DBarStacked100 = 62, xlLineStacked = 63, xlLineStacked100 = 64, xlLineMarkers = 65, xlLineMarkersStacked = 66, xlLineMarkersStacked100 = 67, xlPieOfPie = 68, xlPieExploded = 69, xl3DPieExploded = 70, xlBarOfPie = 71, xlXYScatterSmooth = 72, xlXYScatterSmoothNoMarkers = 73, xlXYScatterLines = 74, xlXYScatterLinesNoMarkers = 75, xlAreaStacked = 76, xlAreaStacked100 = 77, xl3DAreaStacked = 78, xl3DAreaStacked100 = 79, xlDoughnutExploded = 80, xlRadarMarkers = 81, xlRadarFilled = 82, xlSurface = 83, xlSurfaceWireframe = 84, xlSurfaceTopView = 85, xlSurfaceTopViewWireframe = 86, xlBubble = 15, xlBubble3DEffect = 87, xlStockHLC = 88, xlStockOHLC = 89, xlStockVHLC = 90, xlStockVOHLC = 91, xlCylinderColClustered = 92, xlCylinderColStacked = 93, xlCylinderColStacked100 = 94, xlCylinderBarClustered = 95, xlCylinderBarStacked = 96, xlCylinderBarStacked100 = 97, xlCylinderCol = 98, xlConeColClustered = 99, xlConeColStacked = 100, xlConeColStacked100 = 101, xlConeBarClustered = 102, xlConeBarStacked = 103, xlConeBarStacked100 = 104, xlConeCol = 105, xlPyramidColClustered = 106, xlPyramidColStacked = 107, xlPyramidColStacked100 = 108, xlPyramidBarClustered = 109, xlPyramidBarStacked = 110, xlPyramidBarStacked100 = 111, xlPyramidCol = 112, xl3DColumn = 0xFFFFEFFC, xlLine = 4, xl3DLine = 0xFFFFEFFB, xl3DPie = 0xFFFFEFFA, xlPie = 5, xlXYScatter = 0xFFFFEFB7, xl3DArea = 0xFFFFEFFE, xlArea = 1, xlDoughnut = 0xFFFFEFE8, xlRadar = 0xFFFFEFC9 } XlChartType; 小弟嘗試的結果,列出部份常數的意思,其餘的就看有沒有人補充囉! 5:2D的圓形圖(Pie圖) 16:泡泡圖 51:2D的直條圖 52:2D的堆疊直條圖 53:2D的100%堆疊直條圖 54:3D的直條圖 55:3D的堆疊直條圖 56:3D的100%堆疊直條圖 57:2D的橫條圖 58:2D的堆疊橫條圖 59:2D的100%堆疊橫條圖 60:3D的橫條圖 61:3D的堆疊橫條圖 62:3D的100%堆疊橫條圖 63:折線圖 65:含有資料標誌的折線圖 接下來設定EXCEL的背景圖案 String BmpPath; BmpPath="C:\\background.bmp"; if(FileExists(BmpPath)) Worksheet.OleFunction("SetBackgroundPicture",BmpPath.c_str());保護sheet Worksheet.OleFunction("Protect","password",true,true,true,true) ;Protect函式的定義如下: template共有五個參數,第一個是解開保護的Password, 第二個是設定是否要保護sheet上面的 DrawingObjects,像是圖表 第三個是設定是否要保護sheet的Contents,設true的話,使用者不能修改sheet的內容 第四個和第五個是設定是否要保護sheet的Scenarios和UserInterfaceOnly, 不過我不是很清這兩個是保護什麼! Worksheet.OlePropertySet("EnableSelection",xlUnlockedCells);這是要保護使用者連選取cell都不可以, 不過我發現這個保護只能在用OLE製作EXCEL時有效, 如果製作完,把EXCEL關掉,再打開,就又可以選取cell了, 可能有什麼步驟沒做好吧~ ----------------------------------------------------- 有一點很重要,程式中用到的那些常數,像是xlRows、xlcolumns、xlUnlockedCells等, 還有各種圖表格式的定義,以及OLE所提供的所有函數名稱, 都是定義在excel_2k.h這個標頭檔裡, 所以程式前面要加上 #include要不然執行時會出現沒有定義變數這個錯誤, 我很多功能都是看這個標頭檔學來的, 如果想進一步了解OLE 製作Excel還有哪裡功能, 可以試著看看這個檔,不過不容易看~我知道!
------
~~~Delphi K.Top討論區站長~~~ |
領航天使
站長 ![]() ![]() ![]() ![]() ![]() ![]() 發表:12216 回覆:4186 積分:4084 註冊:2001-07-25 發送簡訊給我 |
【文章】如何讓DBGrid按滑鼠右鍵的時候不會影響RowSelect ?
【作者】Justmade
【內文】文章來源:http://delphi.ktop.com.tw/topic.php?topic_id=33637 不用另外繼承,試試將以下程式碼替代
http://delphi.ktop.com.tw/topic.php?TOPIC_ID=33719
範例的程式碼
unit CDSMDForm; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, shellapi, StdCtrls, Grids, DBGrids, DB, DBTables, DBCtrls, DBClient, Provider, jpeg, ExtCtrls; type TDBGrid= class(DBGrids.TDBGrid) protected Procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; end; TForm1 = class(TForm) DataSource1: TDataSource; DBGrid1: TDBGrid; DataSource2: TDataSource; DataSetProvider1: TDataSetProvider; DataSetProvider2: TDataSetProvider; Query1: TQuery; Query2: TQuery; ClientDataSet1: TClientDataSet; ClientDataSet2: TClientDataSet; DBGrid2: TDBGrid; procedure DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState); const // 這個整數值將按照布林值返回,並送入陣列 CtrlState : array[Boolean] of Integer=(DFCS_BUTTONCHECK,DFCS_BUTTONCHECK or DFCS_CHECKED); begin //確保只有在邏輯欄位才能插入元件 if Column.Field.DataType = ftBoolean then begin DBGrid1.Canvas.FillRect(Rect); DrawFrameControl(DBGrid1.Canvas.Handle,Rect,DFC_BUTTON,CtrlState[Column.Field.AsBoolean]); end; end; { TDBGrid } procedure TDBGrid.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if Button <> mbRight then inherited; end; end.並將 DBGrid1 的 poMultiSelect 設 True 便可見右按不會影響 selection 了 另你可換一個有 Boolean Field 的 Table 也可看到不會出現格線不見的情形。 其實看你的多個問題覺得你好像不是用標準的 DBGrid,若時的話你應說清楚免得大家在浪費時間。另你若間題還不能解決你最好做一個簡單的程式包含你的數個間題然後上傳,這樣會比較清楚。
------
~~~Delphi K.Top討論區站長~~~ |
領航天使
站長 ![]() ![]() ![]() ![]() ![]() ![]() 發表:12216 回覆:4186 積分:4084 註冊:2001-07-25 發送簡訊給我 |
【文章】如何判斷TrayIcon的程式是否正在執行?
【作者】Rain
【內文】文章來源:http://delphi.ktop.com.tw/topic.php?topic_id=33946 使用GetModuleFileNameEx即可取得進程路徑(
記得要uses PSAPI單元),如果你的那個應用程式名稱是知道的,則可以
不用FindWindow或EnumWindows,在下面的程式中用if StrPas(ProcessEntry32.szExeFile) = 'yourAppName.exe'替代
if ProcessEntry32.th32ProcessID = AProcessID語句即可 給出完整的程式如下:
uses tlhelp32, ShellAPI, PSAPI; procedure TForm1.Button1Click(Sender: TObject); var Found: Boolean; AProcessID: DWORD; AWnd, AHandle: THandle; ProcessEntry32: TProcessEntry32; APath: array [0..MAX_PATH] of Char; begin AWnd := FindWindow('TMainForm', nil); if AWnd = 0 then Exit; GetWindowThreadProcessId(AWnd, @AProcessID); AHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); try ProcessEntry32.dwSize := Sizeof(ProcessEntry32); Found := Process32First(AHandle, ProcessEntry32); while Found do begin //if StrPas(ProcessEntry32.szExeFile) = ' yourAppName.exe' then ; if ProcessEntry32.th32ProcessID = AProcessID then begin GetModuleFileNameEx(OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, ProcessEntry32.th32ProcessID), 0, @APath[0], SizeOf(APath));//取得進程路徑 TerminateProcess(OpenProcess(PROCESS_ALL_ACCESS, True, ProcessEntry32.th32ProcessID), 0);//結束進程 ShellExecute(Handle, 'open', APath, nil, nil, SW_SHOW);//重新運行程式 //Break; end; Found := Process32Next(AHandle, ProcessEntry32); end; finally CloseHandle(AHandle); end; end;
------
~~~Delphi K.Top討論區站長~~~ |
領航天使
站長 ![]() ![]() ![]() ![]() ![]() ![]() 發表:12216 回覆:4186 積分:4084 註冊:2001-07-25 發送簡訊給我 |
【文章】在image中如何放大缩小jpg文件?
【作者】sos_admin
【內文】文章來源:http://delphi.ktop.com.tw/topic.php?topic_id=38057
1.
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Buttons, ExtCtrls,jpeg; type TForm1 = class(TForm) Image1: TImage; BitBtn1: TBitBtn; procedure FormCreate(Sender: TObject); procedure BitBtn1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; jpgw,jpgh:integer; implementation {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); var jpg:Tjpegimage; begin jpg:=Tjpegimage.Create; jpg.LoadFromFile('c:\1.jpg'); jpgw:=jpg.Width ; jpgh:=jpg.Height ; image1.Width:=jpgw; image1.Height :=jpgh; image1.Picture.Assign(jpg); image1.Stretch:=true; image1.AutoSize:=false; jpg.Free ; end; //i为正数放大,反之缩小 procedure imagesize(image:Timage;i:integer); begin if i>0 then begin image.Width:=jpgw*i ; image.Height:=jpgh*i ; end; if i<0 then begin image.Width:=jpgw div abs(i) ; image.Height:=jpgh div abs(-i) ; end; end; procedure TForm1.BitBtn1Click(Sender: TObject); begin //在原图基础上缩小为原图的1/10 imagesize(image1,-10); end; end.2.
------
~~~Delphi K.Top討論區站長~~~ |
領航天使
站長 ![]() ![]() ![]() ![]() ![]() ![]() 發表:12216 回覆:4186 積分:4084 註冊:2001-07-25 發送簡訊給我 |
【文章】如何防止程式重覆執行?
【作者】axsoft / jessechan
【內文】來源:http://delphi.ktop.com.tw/topic.php?topic_id=36333
1.程式碼下載:http://delphi.ktop.com.tw/loadfile.php?TOPICID=11492747&CC=257033
//--------------------------------------------------------------------------- // 程式名稱: CreateMutexDemo.cpp // 作 者: axsoft // 執行環境: windows XP SPS C Builder 5 Update1 //--------------------------------------------------------------------------- #include2. 如何寫一個Windows應用程式,讓他只執行一次。 -------------------------------------------------------------------------------- 作者:szu (michael liang) 資料來源:高市資教-陽光之都 BBS http://bbs.kh.edu.tw/treasure/Programs/M.991654847.A/M.995983133.A.html 第一種方法(利用FindWindow()): 環境 C Builder Application->Title = ""; HWND hPrevApp = ::FindWindow(NULL, "Title"); //或是寫成HWND hPrevApp = ::FindWindow("Class", NULL); //或是寫成HWND hPrevApp = ::FindWindow("Class", "Title"); if(hPrevApp) { PostMessage(hPrevApp, WM_SYSCOMMAND, SC_RESTORE, 0); return 0; } else { Application->Title = "Title"; } ------------------------------------------------------------------------- 第二種方法(利用FindWindow()): if(FindWindow(NULL, 應用程式的Title)) { return 0; } ------------------------------------------------------------------------- 第三種方法(利用Global Atom Table): ATOM atom; if(GlobalFindAtom("PROGRAM_RUNNING") == 0) { atom = GlobalAddAtom("PROGRAM_RUNNING"); } else { return 0; } 在程式最後請加上 GlobalDeleteAtom(atom); ------------------------------------------------------------------------ 第四種方法(利用Mutex): HANDLE handle = CreateMutex(NULL, false, "MutexName"); DWORD error = GetLastError(); if(error == ERROR_ALREADY_EXISTS ) { return 0; } 記得在程式最後面加入 ReleaseMutex(handle); ------------------------------------------------------------------------ 第五種方法(利用Semaphore): HANDLE handle = CreateSemaphore(NULL, 1, 1, "SemaphoreName"); DWORD error = GetLastError(); if(error == ERROR_ALREADY_EXISTS ) { return 0; } 記得在程式最後面加入 ReleaseSemaphore(handle, 1, NULL);-------------------------------------------------------------------- 以上程式受到智慧財產權的保護, permission to use, copy, modify, and distribute. 但請註明來源出處,不可用於商業用途。 -------------------------------------------------------------------- 3. 我想這個問題已被討論很多次了, 我也曾在這個版上提出同樣的問題, 下面是我找了一些資料加上 RaynorPao 等熱心人士的指點, 所整理的一個心得. 要防止程式重複執行, 在 VB 中的 App 中有一個 preInstance 可以輕易得知目前的程式是否為第一個 instance, 不幸在 BCB 中卻沒有類似的機制, 不過我們可用 CreateMutex 的方法來測試同樣的 Mutex Object 是否已被 create 來確保程式是第一次執行, 其宣告如下, HANDLE CreateMutex( LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCTSTR lpName ); 詳細用法請參考 BCB 的 help 或 MSDN, 這裡我想要提出來的是一般大家在用這個 API 時 lpName 經常使用任意取的名字, 或是直接用 Form 的 Caption, 這樣固然方便但是不能確保名字是唯一, 每次都要想不同的名字又太累, 所以我建議可以做個小修改, AnsiString asTemp00 = (long)(GetWindowLong(Application->Handle,GWL_HINSTANCE)); CreateMutex(NULL,false,asTemp00.c_str()); if (GetLastError() == ERROR_ALREADY_EXISTS) Application->Terminate(); 以程式的 Instance Handle 來個名稱就萬無一失了, 有一點要注意的是在程式結束時要記得 ReleaseMutex(). 另外不知有沒有人想要做到如果之前已有一個 Instance 在執行的話, 就先把之前的程式結束掉, 以後者取代之. 因為如果用 FindWindow 想要去取得前一個程式的 Handle 的話, 找到的總會是自己, 所以必須另找方法, 我所想到的方法是在程式執行時先以 Instance 為 key 把自己的 Handle 存起來, 如此第二個程式在執行時發現已有自己的同類在執行就去讀取它的 Handle, 而對它送出 WM_CLOSE 的 message, 實作如下, #include #include #pragma hdrstop #include "Unit1.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; HWND hMutex; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { TRegistry * rgpSystem = new TRegistry;; Caption = Now(); AnsiString asTemp00 = (long)(GetWindowLong(Application->Handle,GWL_HINSTANCE)); rgpSystem->OpenKey(asTemp00,true); CreateMutex(NULL,false,asTemp00.c_str()); if (GetLastError() == ERROR_ALREADY_EXISTS) SendMessage((HWND)rgpSystem->ReadInteger("Handle"),WM_CLOSE,NULL,NULL); rgpSystem->WriteInteger("Handle",(int)(this->Handle)); rgpSystem->CloseKey(); delete rgpSystem; } //--------------------------------------------------------------------------- void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action) { ReleaseMutex(hMutex); } //--------------------------------------------------------------------------- 這些 code 沒有用到什麼高深的理論, 可是我想還算實用, 野人獻曝, 謹供大家參考. 參考網址:http://delphi.ktop.com.tw/topic.php?topic_id=24297 http://delphi.ktop.com.tw/topic.php?topic_id=24350 ~~~Delphi K.Top討論區站長~~~
------
~~~Delphi K.Top討論區站長~~~ |
領航天使
站長 ![]() ![]() ![]() ![]() ![]() ![]() 發表:12216 回覆:4186 積分:4084 註冊:2001-07-25 發送簡訊給我 |
【文章】如何將寫好的Form快速轉成一個元件?
【作者】bruce0211
【內文】來源:http://delphi.ktop.com.tw/topic.php?topic_id=40137 我發現使用 Form 為 base 的元件可能是所有元件設計中最簡單的方式(因為設計核心時是在一般專案中設計並測試,且可放入任何你想要的元件,如果不是以 Form 為 base 的元件,光想想我們要設計將兩個元件聚合成為一個新元件就已經多不直多困難)
1.設計帶有 Form 的元件,如萬年曆,獨立的對話盒等等,通常這種類型的元件在 user 主 form 中是一不可視元件,也就是插到 Delphi 中只是一個 ICON 而已
(如標準的檔案開啟對話盒元件 TOpenDialog) ,需要用時再利用 if OpenDialog1.Execute then ... 這種方式去呼叫
2.由於這類元件不需在主畫面佔據位置,而是被獨立呼叫(就像是 ShowModal),所以設計元件時可以一般方法設計(可放入許多及任何元件的組合在裡面),如我要設計萬年曆,先用一般方式開一 Project1 專案,以及萬年曆的 unit1.pas & unit1.dfm , 將萬年曆內容寫好,並可 compiler 測試 ok (叫做 project1.exe),我們便可丟掉 project1.* 的檔案,只留下 unit1.pas 及 unit1.dfm 這兩個萬年曆的核心
3.開始設計元件,元件類別繼承自 TComponent , 也就是拿 TComponent 當藥引子,替 TComponent 增加一個公開的方法 "Execute" , 以及 Date 屬性 , 執行 Execute 時, TComponent 實際上是去呼叫完整的萬年曆程式,再將日期回傳 以下為 TMyCalendar 的元件內容 , 可以看出萬年曆程式碼並未寫在裡面,而是另外呼叫 MyCalendarSource.pas (也就是上面舉例的 Unit1.pas) , 而MyCalendarSource.pas 之 Form 名稱叫 FormMyCalendar (也就是上面舉例的 Unit1.dfm) , 整個TMyCalendar 只是當作藥引子 , 實際上萬年曆的程式碼是寫在 MyCalendarSource.pas 中的 其他類似的元件也可依樣畫葫蘆,先用一般方法設計專案設計 Form,測試 OK 後 , 留下 Form 這個部分的程式碼,再套到這個藥引子中
unit MyCalendar; interface uses SysUtils, Classes, Forms, MyCalendarSource; type TMyCalendar = class(TComponent) private { Private declarations } FDate: TDateTime; FRocYear: string; FRocMonth: string; FRocDay:string; procedure DateToRoc(ADate:TDateTime); protected { Protected declarations } public { Public declarations } constructor Create(AOwner : TComponent); override; destructor Destroy; override; function Execute: boolean; overload;//本元件公開的方法 function Execute(ALeft,ATop: integer): boolean; overload; ;//本元件公開的方法(可指定萬年曆出現的座標位置,復疊函式) published { Published declarations } property Date:TDateTime read FDate; //本元件公開的屬性,日期 property RocYear:string read FRocYear; //本元件公開的屬性,民國年 property RocMonth:string read FRocMonth; //本元件公開的屬性,民國月 property RocDay:string read FRocDay;//本元件公開的屬性,民國日 end; procedure Register; implementation constructor TMyCalendar.Create(AOwner : TComponent); begin inherited Create(AOwner); FDate := SysUtils.Date; DateToRoc(FDate); end; destructor TMyCalendar.Destroy; begin inherited Destroy; end; function TMyCalendar.Execute: boolean; var r:integer; begin FormMyCalendar:=TFormMyCalendar.Create(nil); try r:=FormMyCalendar.ShowModal; if r=1 then //mrOK; begin FDate:=FormMyCalendar.SelectDate; DateToRoc(FDate); result:=true; end else result:=false; finally FormMyCalendar.Release; end; end; function TMyCalendar.Execute(ALeft,ATop: integer): boolean; var r:integer; begin FormMyCalendar:=TFormMyCalendar.Create(nil); FormMyCalendar.Position:=poDesigned; FormMyCalendar.Top:=ATop; FormMyCalendar.Left:=ALeft; try r:=FormMyCalendar.ShowModal; if r=1 then //mrOK; begin FDate:=FormMyCalendar.SelectDate; result:=true; end else result:=false; finally FormMyCalendar.Release; end; end; procedure TMyCalendar.DateToRoc(ADate:TDateTime); var TmpYear, TmpMonth, TmpDay : Word; begin DecodeDate(ADate, TmpYear, TmpMonth, TmpDay); FRocYear:=FormatFloat('00',TmpYear-1911); FRocMonth:=FormatFloat('00',TmpMonth); FRocDay:=FormatFloat('00',TmpDay); end; procedure Register; begin RegisterComponents('MyWay', [TMyCalendar]); end; end.~~~Delphi K.Top討論區站長~~~
------
~~~Delphi K.Top討論區站長~~~ |
領航天使
站長 ![]() ![]() ![]() ![]() ![]() ![]() 發表:12216 回覆:4186 積分:4084 註冊:2001-07-25 發送簡訊給我 |
【文章】如何使滑鼠的中間滾輪在DBGrid中可以滾動資料?
【作者】mathewzhao / pwq
【內文】來源:http://delphi.ktop.com.tw/topic.php?topic_id=40777
1.
本人已經解決此問題,現在方法貼出如下:
Type
TDBGrid = class(TDBGrid)
private
FOldGridWnd : TWndMethod;
procedure NewGridWnd (var Message : TMessage);
public
constructor Create(AOwner: TComponent); override;
end;
//////////////////////////////////////////紅色部分代友需放在以下代碼前
TMDFMainForm = class(TForm)
......
end; implementation
{$R *.dfm}
constructor TNDBGrid.Create(AOwner: TComponent);
begin
inherited;
FOldGridWnd := WindowProc;
WindowProc := NewGridWnd;
end; procedure TDBGrid.NewGridWnd(var Message: TMessage);
var
IsNeg : Boolean;
begin
if Message.Msg = WM_MOUSEWHEEL then
begin
IsNeg := Short(Message.WParamHi) < 0;
if IsNeg and (DataSource.DataSet<>nil) and DataSource.DataSet.Active then
DataSource.DataSet.MoveBy(1)
else if not IsNeg and (DataSource.DataSet<>nil) and DataSource.DataSet.Active then
DataSource.DataSet.MoveBy(-1)
end
else FOldGridWnd(Message); end;
........ end.
2. 參考一下這篇文章: http://www.yesky.com/SoftChannel/72342371928440832/20030619/1709082.shtml這樣,我們就基本可以處理鼠標輪事件了,編譯我們的組件,然後選擇菜單Components-Inatll Component,將我們的組件安裝在Samples頁下。 讓我們來試驗一下我們做的組件,新建一個應用,然後選擇Samples下的MyDBGrid組件,其它的用法,和DBGRrid完全一樣,但你可以看見,在你的MyDbGrid的事件中,已經有OnMouseWheel, OnMouseWheelUp, OnMouseWheelDown的選項了。
------
~~~Delphi K.Top討論區站長~~~ |
領航天使
站長 ![]() ![]() ![]() ![]() ![]() ![]() 發表:12216 回覆:4186 積分:4084 註冊:2001-07-25 發送簡訊給我 |
【文章】請問如何得知對方電腦所分享的所有目錄呢?
【作者】japhenchen
【內文】來源:http://delphi.ktop.com.tw/topic.php?topic_id=39584
跑net view \\servername >> nv.txt 或\\ip 就可以顯示對方的共享名稱並且轉向輸出到nv.txt檔~~ 不過,有更好的解決方法
procedure TForm1.Button2Click(Sender: TObject); type TNetResourceArray = ^TNetResource; var NetResource : TNetResource; hr,ecount,BUFSIZE,x: dword; hEnum: THandle; buf : POINTER; ResArray : TNetResourceArray; ResList : TStringList; username: string ; begin username:='\\192.168.1.1'; FillChar(NetResource, SizeOf(NetResource), 0); NetResource.lpRemoteName:=@username[1]; resList:=TStringList.Create; hr:=wnetOpenEnum(RESOURCE_GLOBALNET,RESOURCETYPE_ANY,RESOURCEUSAGE_CONNECTABLE,@NetResource,hEnum); if hr=NO_ERROR then while true do begin BUFSIZE:=8192; GETMEM(BUF,BUFSIZE); ecount := $FFFFFFFF; hr := WNetEnumResource(hEnum,ecount,pointer(buf),bufsize); case hr of ERROR_NO_MORE_ITEMS: break; NO_ERROR : begin ResArray:=TNetResourceArray(buf); for x:= 0 to ecount-1 do begin ResList.Add(ResArray^.lpRemoteName); inc(resArray); end; end; else break; end; end; wnetCloseEnum(hEnum); FreeMem(buf,bufsize); if reslist.count >0 then showmessage(reslist.Text); freeandnil(ResList); end;~~~Delphi K.Top討論區站長~~~
------
~~~Delphi K.Top討論區站長~~~ |
領航天使
站長 ![]() ![]() ![]() ![]() ![]() ![]() 發表:12216 回覆:4186 積分:4084 註冊:2001-07-25 發送簡訊給我 |
【文章】如何判斷是否有該磁碟機?
【作者】hagar
【內文】來源:http://delphi.ktop.com.tw/topic.php?topic_id=20772
function HasDrive(DriveLetter: Char): Boolean; var ld : DWORD; i : integer; sl: TStringList; begin ld := GetLogicalDrives; sl := TStringList.Create; try for i := 0 to 25 do begin if (ld and (1 shl i)) <> 0 then sl.Add(Char(Ord('A') i)); end; Result := (sl.IndexOf(DriveLetter) <> -1); finally sl.Free; end; end; 用法: procedure TForm1.Button1Click(Sender: TObject); begin if HasDrive('C') then ShowMessage('Drive C is valid') else ShowMessage('Drive C is invalid'); end;
------
~~~Delphi K.Top討論區站長~~~ |
領航天使
站長 ![]() ![]() ![]() ![]() ![]() ![]() 發表:12216 回覆:4186 積分:4084 註冊:2001-07-25 發送簡訊給我 |
【文章】讀取Windows的TTF字體輪廓向量資料
【作者】朱朝陽
【內文】來源:http://delphi.ktop.com.tw/topic.php?topic_id=30747 資料來源: http://www2.ccw.com.cn/2000/0031/0031b12.asp 讀取Windows的
TTF字體輪廓向量資料
西安飛機工業公司設計部 朱朝陽
---- Windows系統的TTF字體具有字體優美、可無級縮放等優點,最適合應用在CAD類圖形處理等軟體中。直接分析TTF字體的檔格式並讀出每個字的輪廓向量是相當困難的,我們可以借助API函數來方便地獲得這些資料。
---- 調用函數GetGlyphOutline可以得到一個字的輪廓向量或者點陣圖。
---- 函數原型如下:
DWORD GetGlyphOutline(
HDC hdc, // 設備控制碼
UINT uChar, // 將要讀取的字元
UINT uFormat, // 返回資料的格式
LPGLYPHMETRICS lpgm, // GLYPHMETRICS結構位址
DWORD cbBuffer, // 數據緩衝區的大小
LPVOID lpvBuffer, // 資料緩衝區的位址
CONST MAT2 *lpmat2 // 轉置矩陣的地址
);
---- 其中,參數uFormat取值如下:
GGO_NATIVE - 要求函數返回字元的輪廓向量資料;
GGO_METRICS - 函數僅返回GLYPHMETRICS結構至lpgm;
參數lpgm指向GLYPHMETRICS結構,該結構描述字元的位置。
參數lpmat2指向字元的轉置矩陣。
---- 本文以下C++ Builder程式示範如何在畫布上以指定的大小繪製字串。
---- 首先,建立一個新專案,在主視窗上放置一個Image控制項,一個Edit控制項,一個Button控制項;然後,在Button的點擊事件中加入如下代碼:
#include < stdlib.h > void __fastcall TForm1::Button1Click(TObject *Sender) { TRect ClipRect = Rect(0,0,Image1->Width,Image1->Height); Image1->Picture = 0; StretchTextRect(Image1->Canvas, ClipRect, Edit1->Text); } ---- 添加如下子程式: //--------------------- void TForm1::StretchTextRect(TCanvas *pCanvas, TRect ClipRect, AnsiString Text) { pCanvas->Font->Size = 100; pCanvas->Font->Name = “宋體"; pCanvas->Pen->Color = clBlack; pCanvas->Pen->Mode = pmCopy; pCanvas->Pen->Style = psSolid; pCanvas->Pen->Width = 1; int XSize = ClipRect.Width() / Text.Length(); int YSize = ClipRect.Height(); MAT2 mat2; // 轉置矩陣,不用變換 mat2.eM11.value = 1;mat2.eM11.fract = 0; mat2.eM12.value = 0;mat2.eM12.fract = 0; mat2.eM21.value = 0;mat2.eM21.fract = 0; mat2.eM22.value = 1;mat2.eM22.fract = 0; GLYPHMETRICS gm,gmm; // 首先獲得字元的位置矩陣,存入gm GetGlyphOutlineA(pCanvas->Handle,0x0b0a1, GGO_METRICS,&gm,0,NULL,&mat2); char *ptr = Text.c_str(); TRect TheRect; for(int i = 0;i < Text.Length();) { int c1 = (unsigned char)*ptr; int c2 = (unsigned char)*(ptr + 1); UINT nChar; TheRect.Left = i * XSize + ClipRect.Left; TheRect.Top = ClipRect.Top; TheRect.Right = (i + 2) * XSize + ClipRect.Left; TheRect.Bottom = ClipRect.Top + YSize; if(c1 > 127) { // 當前字元是漢字 nChar = c1 * 256 + c2; ptr+=2;i+=2; } else { // 字母或數位 nChar = c1; ptr++;i++; } // 獲得當前字元資料的陣列的大小 DWORD cbBuffer = GetGlyphOutlineA(pCanvas-> Handle,nChar,GGO_NATIVE,&gmm,0,NULL,&mat2); if(cbBuffer == GDI_ERROR) break; void *lpBuffer = malloc(cbBuffer); if(lpBuffer != NULL) { // 讀入數據置緩衝區 if(GetGlyphOutlineA(pCanvas-> Handle,nChar,GGO_NATIVE, &gmm,cbBuffer,lpBuffer,&mat2) != GDI_ERROR) { // 分析資料並繪製字元 TMemoryStream *MBuffer = new TMemoryStream(); MBuffer->Write(lpBuffer,cbBuffer); MBuffer->Position = 0; for(;MBuffer->Position < MBuffer->Size;) { int CurPos = MBuffer->Position; TTPOLYGONHEADER polyheader; int ptn = 0; MBuffer->Read(&polyheader,sizeof(polyheader)); ptn++; for(int j = 0;j < (int)(polyheader.cb - sizeof(polyheader));) { WORD wtype,cpfx; MBuffer->Read(&wtype,sizeof(WORD)); MBuffer->Read(&cpfx,sizeof(WORD)); MBuffer->Position += cpfx * sizeof(POINTFX); j += sizeof(WORD) * 2 + cpfx * sizeof(POINTFX); if(wtype == TT_PRIM_LINE) ptn += cpfx; else ptn += (cpfx - 1) * 3 + 1; } TPoint *pts = new TPoint[ptn+1]; // 存儲多邊形頂點 MBuffer->Position = CurPos; ptn = 0; MBuffer->Read(&polyheader,sizeof(polyheader)); TPoint pt0 = POINTFX2TPoint(polyheader.pfxStart,TheRect,&gm); pts[ptn++] = pt0; for(int j = 0;j < (int)(polyheader.cb - sizeof(polyheader));) { TPoint pt1; WORD wtype,cpfx; MBuffer->Read(&wtype,sizeof(WORD)); MBuffer->Read(&cpfx,sizeof(WORD)); POINTFX *pPfx = new POINTFX[cpfx]; MBuffer->Read((void *)pPfx,cpfx * sizeof(POINTFX)); j += sizeof(WORD) * 2 + cpfx * sizeof(POINTFX); if(wtype == TT_PRIM_LINE) { // 直線段 for(int i = 0;i < cpfx;i++) { pt1 = POINTFX2TPoint(pPfx[i],TheRect,&gm); pts[ptn++] = pt1; } } else { // Bezier曲線 TPoint p0,p1,p2,p3,p11,p22,pp0,pp1,pp2,pt11,pt22; int i; for(i = 0;i < cpfx-1;i++) { pt11 = POINTFX2TPoint(pPfx[i],TheRect,&gm); pt22 = POINTFX2TPoint(pPfx[i+1],TheRect,&gm); pp0 = pts[ptn-1]; pp1 = pt11; pp2.x = (pt11.x + pt22.x)/2; pp2.y = (pt11.y + pt22.y)/2; p0 = pp0; p1.x = pp0.x/3 + 2 * pp1.x/3; p1.y = pp0.y/3 + 2 * pp1.y/3; p2.x = 2 * pp1.x/3 + pp2.x/3; p2.y = 2 * pp1.y/3 + pp2.y/3; p3 = pp2; for(float t = 0.0f;t <= 1.0f;t += 0.5f) { float x = (1-t)*(1-t)*(1-t)*p0.x+ 3*t*(1-t)*(1-t)*p1.x+ 3*t*t *(1-t)*p2.x + t*t*t*p3.x; float y = (1-t)*(1-t)*(1-t)*p0.y + 3*t*(1-t)*(1-t)*p1.y+3 *t*t*(1-t)*p2.y + t*t*t*p3.y; pts[ptn].x = x; pts[ptn].y = y; ptn++; } } pt1 = POINTFX2TPoint(pPfx[i],TheRect,&gm); pts[ptn++] = pt1; } delete pPfx; } pts[ptn] = pts[0]; // 封閉多邊形 pCanvas->Brush->Color = clWhite; pCanvas->Pen->Mode = pmXor; pCanvas->Pen->Style = psClear; pCanvas->Brush->Style = bsSolid; pCanvas->Polygon(pts,ptn); delete pts; } delete MBuffer; } free(lpBuffer); } } } //--------------------- TPoint TForm1::POINTFX2TPoint(POINTFX pf, TRect TheRect,GLYPHMETRICS *gm) { TPoint point; float fx,fy; fx = pf.x.value + pf.x.fract / 65536.0f + 0.5f; fx = fx / (float)(gm->gmBlackBoxX + gm->gmptGlyphOrigin.x) * (float)TheRect.Width() + (float)TheRect.Left; fy = pf.y.value + pf.y.fract / 65536.0f + 0.5f; fy = ((float)gm->gmBlackBoxY - fy) / (float)(gm->gmBlackBoxX + gm->gmptGlyphOrigin.x) * (float)TheRect.Height() + (float)TheRect.Top; point.x = int(fx); point.y = int(fy); return point; }
------
~~~Delphi K.Top討論區站長~~~ |
領航天使
站長 ![]() ![]() ![]() ![]() ![]() ![]() 發表:12216 回覆:4186 積分:4084 註冊:2001-07-25 發送簡訊給我 |
【文章】如何開啟Excel並限制只能編輯某一頁sheet?
【作者】timhuang
【內文】來源:http://delphi.ktop.com.tw/topic.php?topic_id=29580 下面的程式範例為新開一個excel檔案後, 將 Sheet1, Sheet2 定為保護, 並切至 Sheet3 讓使用者輸入!!
procedure TForm1.Button1Click(Sender: TObject); var ex, wb, ws: variant; begin ex := CreateOleObject('Excel.Application'); wb := ex.WorkBooks.Add; ex.visible := true; wb.Sheets['Sheet3'].Select; //利用 workbook 的 sheets 給定名稱或是指定第幾個都可以, 再利用 select 來進行選取的動作 //下面的兩行是以文件保護的方式來不讓使用者修改 wb.Sheets['Sheet1'].Protect(DrawingObjects:=True, Contents:=True, Scenarios:=True); wb.Sheets['Sheet2'].Protect(DrawingObjects:=True, Contents:=True, Scenarios:=True); end;
------
~~~Delphi K.Top討論區站長~~~ |
領航天使
站長 ![]() ![]() ![]() ![]() ![]() ![]() 發表:12216 回覆:4186 積分:4084 註冊:2001-07-25 發送簡訊給我 |
【文章】TComm安裝與16進制傳送接收程式
【作者】bt1
【內文】來源:http://delphi.ktop.com.tw/topic.php?topic_id=35700 本RS232的元件是由書本[c++ Builder與RS232串列通訊控制]內ch4所附的元件. 安裝方式:
step1:把TComm資料夾copy到C:\Program Files\Borland\CBuilder5 step2:開啟BCB5 step3:進入Compoment--->Install Component--->在Into existing package中的Unit file name中按
Browse按鈕,設路徑為C:\Program Files\Borland\CBuilder5\TComm
選Comm.cpp step4: 安裝完,關閉BCB5,並儲存檔案. step5:開啟BCB5,可以在上面一排元件中的system中看到TComm元件(一個9pin的Rs232端子,下方數字1010) setp6:安裝完成. [運用] 開啟: Comm1->PortOpen = true; 傳送: Comm1->OutputByte(ByteSend); 接收: ByteReceive=Comm1->ReadInputByte(); 關閉: Comm1->PortOpen=false; 全域變數的宣告:
DynamicArray
------
~~~Delphi K.Top討論區站長~~~ |
領航天使
站長 ![]() ![]() ![]() ![]() ![]() ![]() 發表:12216 回覆:4186 積分:4084 註冊:2001-07-25 發送簡訊給我 |
【文章】如何抓取WINDOWS系統預設的輸入法
【作者】P.D.
【內文】來源:http://delphi.ktop.com.tw/topic.php?topic_id=42278
一些常用的輸入法設定, 直接引用就可以, 但 TsysUt 是formname, 請自行修正
private function GetIMEList(dCombobox: TComboBox): integer; function GetImeFileName: string; function SetActiveIme(sWanted: string): boolean; function SetFirstIme: boolean; function SetCloseIme: boolean; function SetKey2Ime(aObj: TWinControl): boolean; .... // 取得window內所有的輸入法 function TSysUt.GetIMEList(dCombobox: TComboBox): integer; var iHandleCount: integer; pList: array[1..nHKL_LIST] of HKL; szImeFileName: array[0..MAX_PATH] of char; sImeFileName: string; i: integer; begin // 看看是否安裝了這個輸入法 iHandleCount:= GetKeyboardLayoutList(nHKL_LIST, pList); for i:= 1 to iHandleCount do begin ImmGetDescription(pList[i], szImeFileName, MAX_PATH); sImeFileName := trim(AnsiUpperCase(StrPas(szImeFileName))); dCombobox.Items.Add(sImeFileName); end; dCombobox.Items.Strings[0]:= ''; result:= iHandleCount; end; //偵測目前作用中的輸入法檔案名稱 function TSysUT.GetImeFileName: string; var szImeFileName: array[0..MAX_PATH] of char; begin if ImmGetDescription(GetKeyboardLayout(0), szImeFileName, MAX_PATH) <> 0 then result:= AnsiUpperCase(StrPas(szImeFileName)) else result:= ''; end; // 切換到指定的輸入法 function TSysUT.SetActiveIme(sWanted: string): boolean; var iHandleCount: integer; pList: array[1..nHKL_LIST] of HKL; szImeFileName: array[0..MAX_PATH] of char; sImeFileName: string; bInstalled: boolean; i: integer; begin result:= False; sWanted:= AnsiUpperCase(sWanted); // 看看是否安裝了這個輸入法 bInstalled:= False; iHandleCount:= GetKeyboardLayoutList(nHKL_LIST, pList); for i:= 1 to iHandleCount do begin ImmGetDescription(pList[i], szImeFileName, MAX_PATH); sImeFileName := AnsiUpperCase(StrPas(szImeFileName)); if pos(sWanted,sImeFileName)>0 then begin bInstalled:= True; break; end; end; // 如果這個輸入法已安裝了, 讓那個輸入法的鍵盤分佈(KeyLayout)作用 if bInstalled then begin ActivateKeyboardLayout(pList[i], 0); result:= True; end; end; // 切換到第一個輸入法 function TSysUT.SetFirstIme: boolean; var iHandleCount: integer; pList: array[1..nHKL_LIST] of HKL; szImeFileName: array[0..MAX_PATH] of char; begin iHandleCount:= GetKeyboardLayoutList(nHKL_LIST, pList); if iHandleCount>=2 then begin ImmGetDescription(pList[2], szImeFileName, MAX_PATH); ActivateKeyboardLayout(pList[2], 0); result:= True; end else result:= False; end; // 回英數輸入法, 本輸入法假設第一組為英數 function TSysUT.SetCloseIme: boolean; var iHandleCount: integer; pList: array[1..nHKL_LIST] of HKL; szImeFileName: array[0..MAX_PATH] of char; begin U_VarDef.ChangeIME:= SysUT.GetImeFileName; iHandleCount:= GetKeyboardLayoutList(nHKL_LIST, pList); if iHandleCount>0 then begin ImmGetDescription(pList[1], szImeFileName, MAX_PATH); ActivateKeyboardLayout(pList[1], 0); result:= True; end else result:= False; end; //模擬ctrl-space來切換中英文 function TSysUT.SetKey2Ime(aObj: TWinControl): boolean; begin ImmSimulateHotKey(aObj.Handle, IME_THOTKEY_IME_NONIME_TOGGLE); result:= True; end;// 取得window所有輸入法用法 GetIMEList(combobox1); // 切換到注音 (字串須依window不同版本所提供, 可用上述function查得 SetActiveIme('注音');
------
~~~Delphi K.Top討論區站長~~~ |
領航天使
站長 ![]() ![]() ![]() ![]() ![]() ![]() 發表:12216 回覆:4186 積分:4084 註冊:2001-07-25 發送簡訊給我 |
【文章】不用標題欄也可以移動表單
【作者】未知
【內文】來源:http://delphi.ktop.com.tw/topic.php?topic_id=37720 不用標題欄也可以移動表單 一般情況下,移動一個表單需要將滑鼠放置在標題欄上才能拖動表單,d什l非要使用標題欄呢?其實我們可以使用一個巧妙的方法來實現將滑鼠放置在表單上按下就可拖動表單,下面先看實現代碼。在Form1的“Private”部分聲明過程:
在private部分加入下列代碼:
procedure wmnchittest(var msg:twmnchittest);
message wm_nchittest;
在程式部分加入以下代碼:
procedure TForm1.wmnchittest(var msg:twmnchittest);
begin
inherited;
if (htclient=msg.result) then msg.result:=htcaption;
end;
上面的關鍵代碼雖然只有兩行,但它實現了滑鼠直接拖動表單的目的。代碼的原理是利用表單的WM_NCHITTEST消息,這個消息是當游標移動、滑鼠按下或釋放時發生的,當程式檢測到滑鼠在表單中按下的消息後(消息的值dhtClient),將滑鼠在標題欄上按下時{生的消息(值dhtCaption)傳遞出去,這樣就巧妙的欺騙程式認d是標題欄被按下,當然就可拖動表單了。
------
~~~Delphi K.Top討論區站長~~~ |
領航天使
站長 ![]() ![]() ![]() ![]() ![]() ![]() 發表:12216 回覆:4186 積分:4084 註冊:2001-07-25 發送簡訊給我 |
【文章】如何像ie一樣儲存完整網頁(包含圖片...)
【作者】hagar
【內文】來源:http://delphi.ktop.com.tw/topic.php?topic_id=42605 下面的這一段程式碼只能儲存網頁的原始碼:
uses ActiveX;
procedure TForm1.Button1Click(Sender: TObject);
begin
(WebBrowser1.Document as IPersistFile).Save('C:\test.htm', False);
end; 以下的這一段程式就可以儲存完整的網頁內容(包含圖片...)
但是會出現對話匡
begin
WebBrowser1.ExecWB(OLECMDID_SAVEAS,
OLECMDEXECOPT_DODEFAULT,
EmptyParam,
EmptyParam);
end; 參考資料:http://groups.google.com.tw/groups?hl=zh-TW&lr=&ie=UTF-8&oe=UTF-8&th=878502bb87a888e6&rnum=11
------
~~~Delphi K.Top討論區站長~~~ |
領航天使
站長 ![]() ![]() ![]() ![]() ![]() ![]() 發表:12216 回覆:4186 積分:4084 註冊:2001-07-25 發送簡訊給我 |
【文章】如何取得 WebBrowser 內所有的連結
【作者】hagar
【內文】來源:http://delphi.ktop.com.tw/topic.php?topic_id=42605
procedure TForm1.Button1Click(Sender: TObject); var i: Integer; begin for i := 0 to Webbrowser1.OleObject.Document.links.Length - 1 do Listbox1.Items.Add(Webbrowser1.OleObject.Document.Links.Item(i)); end; {*****************} { if there are frames } procedure TForm1.Button2Click(Sender: TObject); var u : variant; v : IDispatch; s : string; procedure RecurseLinks(htmlDoc: variant); var BodyElement : variant; ElementCo: variant; HTMLFrames: variant; HTMLWnd : variant; j, i : integer; begin if VarIsEmpty(htmlDoc) then exit; BodyElement := htmlDoc.body; if BodyElement.tagName = 'BODY' then begin ElementCo := htmlDoc.links; j := ElementCo.Length - 1; for i := 0 to j do begin u := ElementCo.item(i); s := u.href; listLinks.Items.Add(s); end; end; HTMLFrames := htmlDoc.Frames; j := HTMLFrames.length - 1; for i := 0 to j do begin HTMLWnd := HTMLFrames.Item(i); RecurseLinks(HTMLWnd.Document); end; end; // RecurseLinks begin v := WebBrowser1.document; listLinks.Clear; RecurseLinks(v); end;參考資料: http://www.swissdelphicenter.ch/en/showcode.php?id=479
------
~~~Delphi K.Top討論區站長~~~ |
領航天使
站長 ![]() ![]() ![]() ![]() ![]() ![]() 發表:12216 回覆:4186 積分:4084 註冊:2001-07-25 發送簡訊給我 |
【文章】HTML與ActiveForm間的參數如何傳遞?
【作者】mi86018
【內文】http://delphi.ktop.com.tw/topic.php?topic_id=22699
[問題]
我利用ActiveForm撰寫了一個OCX檔,然後利用下列方式在HTML中
設定Active Form的Color屬性,讓User讀取網頁時出現不同的色彩
,如果我想自己加上一個TEST的屬性,來作其他參數傳遞不知是否可
行? 請問是否有人這樣使用過. classid="clsid:FC5F3xxx-2xxx-4xx4-Bxxx-3xxxxx9xxxxx"
codebase="http://www.xxx.xxx.tw/AAAA.cab#version=1,0,0,54"
width=380
height=298 param name="Color" value="129"
param name="TEST" value="參數傳遞" <=自行編輯的TEST屬性,用來傳遞資料 [回覆]
寫好的Activex ocx 在HTML引用的程式碼如下:
<OBJECT " classid="clsid:4BBF9074-8799-41D9-B4E8-BF93C4372E6B" codebase="./PrintBarcodeProj1.inf" width=117 height=47 align=center hspace=0 vspace=0 ><font color=red>"> </OBJECT></font>紅色這行..就是要從Html要傳入ocx的參數。 而在Delphi中的ActiveX Form中點選 View -> Type Library 然後點選有個像紅色棒棒糖的Interface然後點滑鼠右鍵,New一個新的property,如圖一。 function Get_BarcodeStr: WideString; safecall; procedure Set_BarcodeStr(const Value: WideString); safecall;在這兩個函式裡面,要加上下面的程式碼,當然也可以加入一些你自己需要的程式。 function TActiveXForm1.Get_BarcodeStr: WideString; begin Result := WideString(BarcodeStr); end; procedure TActiveXForm1.Set_BarcodeStr(const Value: WideString); begin BarcodeStr := Value; end;之後,就可以在你自己寫的其他函式裡面用的這個從Html傳進來的參數了,用法如下: 例如我在Timer裡面用道: procedure TActiveXForm1.Timer1Timer(Sender: TObject); var str:String; begin Timer1.Enabled:=False; str := get_BarcodeStr; if (length(str) = 0) then exit else showmessage(str); end;將這個form包成ocx,Deploy之後,在Html語法記得加上文章最上面的那行 ">這樣這個網頁就能將參數傳進這個ocx了!!
------
~~~Delphi K.Top討論區站長~~~ |
領航天使
站長 ![]() ![]() ![]() ![]() ![]() ![]() 發表:12216 回覆:4186 積分:4084 註冊:2001-07-25 發送簡訊給我 |
|
領航天使
站長 ![]() ![]() ![]() ![]() ![]() ![]() 發表:12216 回覆:4186 積分:4084 註冊:2001-07-25 發送簡訊給我 |
【文章】如何判斷執行檔執行中?如何刪除執行工作?
【作者】ko
【內文】http://delphi.ktop.com.tw/topic.php?topic_id=34139 unit Unit1; interface uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls; type
TForm1 = class(TForm)
Button1: TButton;
Edit1: TEdit;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end; var
Form1: TForm1; implementation {$R *.dfm}
uses TlHelp32;
var spid:Integer;
PH : THandle; function ApplicationUse(fName : string) : boolean;
var
hSS: THandle;
ProcEntry32: PROCESSENTRY32;
iCount: Integer;
begin
Result := False;
iCount := 0;
hSS := CreateToolHelp32Snapshot(TH32CS_SNAPALL, 0);
ProcEntry32.dwSize := sizeof(ProcEntry32);
//-----------------
if Process32First(hSS, ProcEntry32) then
begin
repeat
// Application.MessageBox((ProcEntry32.szExeFile),'...');
if UpperCase(ProcEntry32.szExeFile) = UpperCase(fName) then
begin spid := ProcEntry32.th32ProcessID;
Inc(iCount);
if iCount >= 1 then
begin
Result := True;
Break;
end;
end; until not Process32Next(hSS, ProcEntry32);
CloseHandle(hSS);
end;
//--------------
if Result then Exit;
end; function KillSelectedProcess(PID:integer):String;
var
lpExitCode : DWord;
hProcess : Cardinal;
begin
hProcess := Int64(PID);
PH := OpenProcess(PROCESS_TERMINATE or PROCESS_QUERY_INFORMATION,FALSE, hProcess);
if PH <> 0 then
begin
if GetExitCodeProcess(PH, lpExitCode) then
TerminateProcess(PH, lpExitCode)
else
Result := 'Could not retreive the ExitCode for this process.';
CloseHandle(PH);
end
else
Result := 'Could not get access to this process.'
end; procedure TForm1.Button1Click(Sender: TObject);
begin
if ApplicationUse(edit1.text) then
begin
KillSelectedProcess(spid);
end;
end; end. ~~~Delphi K.Top討論區站長~~~
------
~~~Delphi K.Top討論區站長~~~ |
領航天使
站長 ![]() ![]() ![]() ![]() ![]() ![]() 發表:12216 回覆:4186 積分:4084 註冊:2001-07-25 發送簡訊給我 |
【文章】combobox中下拉後的內容不夠寬怎辦?
【作者】hagar
【內文】http://delphi.ktop.com.tw/topic.php?topic_id=24612
procedure SetComboDropDownWidth(ComboBox: TComboBox; Width: Longint = -1); var I, TextLen: Longint; begin if Width < ComboBox.Width then begin ComboBox.Canvas.Handle := GetDC(ComboBox.Handle); try for I := 0 to ComboBox.Items.Count -1 do begin TextLen := ComboBox.Canvas.TextWidth(ComboBox.Items[I]); if TextLen > Width then Width := TextLen; end; (* Standard ComboBox drawing is Rect.Left 2, adding the extra spacing offsets this *) Inc(Width, 10); finally ReleaseDC(ComboBox.Handle, ComboBox.Canvas.Handle); end; end; SendMessage(ComboBox.Handle, CB_SETDROPPEDWIDTH, Width, 0); end; --~~~Delphi K.Top討論區站長~~~
------
~~~Delphi K.Top討論區站長~~~ |
領航天使
站長 ![]() ![]() ![]() ![]() ![]() ![]() 發表:12216 回覆:4186 積分:4084 註冊:2001-07-25 發送簡訊給我 |
【文章】如何出現網路上的芳鄰選擇視窗?
【作者】Miles
【內文】http://delphi.ktop.com.tw/topic.php?topic_id=41923
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; Edit1: TEdit; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} Uses ShellAPI, ShlObj; function BrowseForComputer(const Title : String) : String; var BrowseInfo : TBROWSEINFO; IDRoot : PItemIDList; Path : array[0..MAX_PATH] of char; begin SHGetSpecialFolderLocation(Application.Handle, CSIDL_NETWORK, IDRoot); FillChar(BrowseInfo, sizeof(TBrowseInfo), #0); FillChar(Path, sizeof(Path), #0); BrowseInfo.hwndOwner := Application.Handle; BrowseInfo.pidlRoot := IDRoot; BrowseInfo.lpszTitle := PChar(Title); BrowseInfo.pszDisplayName := @Path; BrowseInfo.ulFlags := BIF_BROWSEFORCOMPUTER; SHBrowseForFolder(BrowseInfo); Result := String(Path); end; procedure TForm1.Button1Click(Sender: TObject); begin Edit1.Text := BrowseForComputer('網路芳鄰選我'); end; end.
------
~~~Delphi K.Top討論區站長~~~ |
領航天使
站長 ![]() ![]() ![]() ![]() ![]() ![]() 發表:12216 回覆:4186 積分:4084 註冊:2001-07-25 發送簡訊給我 |
【文章】幾個有用的日期轉換函數(包含UNIXTIME轉換)
【作者】Trevor J Carlsen
【內文】來源:http://www.bsdg.org/swag/DATETIME/0015.PAS.html
Unit TCDate; { Author: Trevor J Carlsen Released into the public domain } { PO Box 568 } { Port Hedland } { Western Australia 6721 } { Voice 61 91 732 026 } Interface Uses Dos; Type Date = Word; UnixTimeStamp = LongInt; Const WeekDays : Array[0..6] of String[9] = ('Sunday','Monday','Tuesday','Wednesday','Thursday', 'Friday','Saturday'); months : Array[1..12] of String[9] = ('January','February','March','April','May','June','July', 'August','September','October','November','December'); Function DayofTheWeek(pd : date): Byte; { Returns the day of the week For any date Sunday = 0 .. Sat = 6 } { pd = a packed date as returned by the Function PackedDate } { eg... Writeln('today is ',WeekDays[DayofTheWeek(today))]; } Function PackedDate(yr,mth,d: Word): date; { Packs a date into a Word which represents the number of days since } { Dec 31,1899 01-01-1900 = 1 } Function UnixTime(yr,mth,d,hr,min,sec: Word): UnixTimeStamp; { Packs a date and time into a four Byte unix style Variable which } { represents the number of seconds that have elapsed since midnight } { on Jan 1st 1970. } Procedure UnPackDate(Var yr,mth,d: Word; pd : date); { Unpacks a Word returned by the Function PackedDate into its } { respective parts of year, month and day } Procedure UnPackUnix(Var yr,mth,d,hr,min,sec: Word; uts: UnixTimeStamp); { Unpacks a UnixTimeStamp Variable into its Component parts. } Function DateStr(pd: date; Format: Byte): String; { Unpacks a Word returned by the Function PackedDate into its } { respective parts of year, month and day and then returns a String } { Formatted according to the specifications required. } { if the Format is > 9 then the day of the week is prefixed to the } { returned String. } { Formats supported are: } { 0: dd/mm/yy } { 1: mm/dd/yy } { 2: dd/mm/yyyy } { 3: mm/dd/yyyy } { 4: [d]d xxx yyyy (xxx is alpha month of 3 Chars) } { 5: xxx [d]d, yyyy } { 6: [d]d FullAlphaMth yyyy } { 7: FullAlphaMth [d]d, yyyy } { 8: [d]d-xxx-yy } { 9: xxx [d]d, 'yy } Function ValidDate(yr,mth,d : Word; Var errorcode : Byte): Boolean; { Validates the date and time data to ensure no out of range errors } { can occur and returns an error code to the calling Procedure. A } { errorcode of zero is returned if no invalid parameter is detected. } { Errorcodes are as follows: } { Year out of range (< 1901 or > 2078) bit 0 of errorcode is set. } { Month < 1 or > 12 bit 1 of errorcode is set. } { Day < 1 or > 31 bit 2 of errorcode is set. } { Day out of range For month bit 2 of errorcode is set. } Procedure ParseDateString(Var dstr; Var y,m,d : Word; Format : Byte); { Parses a date String in several Formats into its Component parts } { It is the Programmer's responsibility to ensure that the String } { being parsed is a valid date String in the Format expected. } { Formats supported are: } { 0: dd/mm/yy[yy] } { 1: mm/dd/yy[yy] } Function NumbofDaysInMth(y,m : Word): Byte; { returns the number of days in any month } Function IncrMonth(pd: date; n: Word): date; { Increments pd by n months. } Function today : date; { returns the number of days since 01-01-1900 } Function ordDate (Y,M,D : Word):LongInt; { returns ordinal Date yyddd } Function Dateord (S : String) : String; { returns Date as 'yymmdd' } {============================================================================= } Implementation Const TDays : Array[Boolean,0..12] of Word = ((0,31,59,90,120,151,181,212,243,273,304,334,365), (0,31,60,91,121,152,182,213,244,274,305,335,366)); UnixDatum = LongInt(25568); SecsPerDay = 86400; SecsPerHour = LongInt(3600); SecsPerMin = LongInt(60); MinsPerHour = 60; Function DayofTheWeek(pd : date): Byte; begin DayofTheWeek := pd mod 7; end; { DayofTheWeek } Function PackedDate(yr,mth,d : Word): date; { valid For all years 1901 to 2078 } Var temp : Word; lyr : Boolean; begin lyr := (yr mod 4 = 0); if yr >= 1900 then dec(yr,1900); temp := yr * Word(365) (yr div 4) - ord(lyr); inc(temp,TDays[lyr][mth-1]); inc(temp,d); PackedDate := temp; end; { PackedDate } Function UnixTime(yr,mth,d,hr,min,sec: Word): UnixTimeStamp; { Returns the number of seconds since 00:00 01/01/1970 } begin UnixTime := SecsPerDay * (PackedDate(yr,mth,d) - UnixDatum) SecsPerHour * hr SecsPerMin * min sec; end; { UnixTime } Procedure UnPackDate(Var yr,mth,d: Word; pd : date); { valid For all years 1901 to 2078 } Var julian : Word; lyr : Boolean; begin d := pd; yr := (LongInt(d) * 4) div 1461; julian := d - (yr * 365 (yr div 4)); inc(yr,1900); lyr := (yr mod 4 = 0); inc(julian,ord(lyr)); mth := 0; While julian > TDays[lyr][mth] do inc(mth); d := julian - TDays[lyr][mth-1]; end; { UnPackDate } Procedure UnPackUnix(Var yr,mth,d,hr,min,sec: Word; uts: UnixTimeStamp); Var temp : UnixTimeStamp; begin UnPackDate(yr,mth,d,date(uts div SecsPerDay) UnixDatum); temp := uts mod SecsPerDay; hr := temp div SecsPerHour; min := (temp mod SecsPerHour) div MinsPerHour; sec := temp mod SecsPerMin; end; { UnPackUnix } Function DateStr(pd: date; Format: Byte): String; Var y,m,d : Word; YrStr : String[5]; MthStr : String[11]; DayStr : String[8]; TempStr : String[5]; begin UnpackDate(y,m,d,pd); str(y,YrStr); str(m,MthStr); str(d,DayStr); TempStr := ''; if Format > 9 then TempStr := copy(WeekDays[DayofTheWeek(pd)],1,3) ' '; if (Format mod 10) < 4 then begin if m < 10 then MthStr := '0' MthStr; if d < 10 then DayStr := '0' DayStr; end; Case Format mod 10 of { Force Format to a valid value } 0: DateStr := TempStr DayStr '/' MthStr '/' copy(YrStr,3,2); 1: DateStr := TempStr MthStr '/' DayStr '/' copy(YrStr,3,2); 2: DateStr := TempStr DayStr '/' MthStr '/' YrStr; 3: DateStr := TempStr MthStr '/' DayStr '/' YrStr; 4: DateStr := TempStr DayStr ' ' copy(months[m],1,3) ' ' YrStr; 5: DateStr := TempStr copy(months[m],1,3) ' ' DayStr ' ' YrStr; 6: DateStr := TempStr DayStr ' ' months[m] ' ' YrStr; 7: DateStr := TempStr months[m] ' ' DayStr ' ' YrStr; 8: DateStr := TempStr DayStr '-' copy(months[m],1,3) '-' copy(YrStr,3,2); 9: DateStr := TempStr copy(months[m],1,3) ' ' DayStr ', ''' copy(YrStr,3,2); end; { Case } end; { DateStr } Function ValidDate(yr,mth,d : Word; Var errorcode : Byte): Boolean; begin errorcode := 0; if (yr < 1901) or (yr > 2078) then errorcode := (errorcode or 1); if (d < 1) or (d > 31) then errorcode := (errorcode or 2); if (mth < 1) or (mth > 12) then errorcode := (errorcode or 4); Case mth of 4,6,9,11: if d > 30 then errorcode := (errorcode or 2); 2: if d > (28 ord((yr mod 4) = 0)) then errorcode := (errorcode or 2); end; {Case } ValidDate := (errorcode = 0); if errorcode <> 0 then Write(#7); end; { ValidDate } Procedure ParseDateString(Var dstr; Var y,m,d : Word; Format : Byte); Var left,middle : Word; errcode : Integer; st : String Absolute dstr; begin val(copy(st,1,2),left,errcode); val(copy(st,4,2),middle,errcode); val(copy(st,7,4),y,errcode); Case Format of 0: begin d := left; m := middle; end; 1: begin d := middle; m := left; end; end; { Case } end; { ParseDateString } Function NumbofDaysInMth(y,m : Word): Byte; { valid For the years 1901 - 2078 } begin Case m of 1,3,5,7,8,10,12: NumbofDaysInMth := 31; 4,6,9,11 : NumbofDaysInMth := 30; 2 : NumbofDaysInMth := 28 ord((y mod 4) = 0); end; end; { NumbofDaysInMth } Function IncrMonth(pd: date; n: Word): date; Var y,m,d : Word; begin UnpackDate(y,m,d,pd); dec(m); inc(m,n); inc(y,m div 12); { if necessary increment year } m := succ(m mod 12); if d > NumbofDaysInMth(y,m) then d := NumbofDaysInMth(y,m); IncrMonth := PackedDate(y,m,d); end; { IncrMonth } Function today : date; Var y,m,d,dw : Word; begin GetDate(y,m,d,dw); today := PackedDate(y,m,d); end; { today } Function ordDate (Y,M,D : Word): LongInt; { returns ordinal Date as yyddd } Var LYR : Boolean; TEMP : LongInt; begin LYR := (Y mod 4 = 0) and (Y <> 1900); Dec (Y,1900); TEMP := LongInt(Y) * 1000; Inc (TEMP,TDays[LYR][M-1]); { Compute # days through last month } Inc (TEMP,D); { # days this month } ordDate := TEMP end; { ordDate } Function Dateord (S : String) : String; { returns Date as 'yymmdd' } Var LYR : Boolean; Y,M,D : Word; TEMP : LongInt; N : Integer; StoP : Boolean; SW,ST : String[6]; begin Val (Copy(S,1,2),Y,N); Val (Copy(S,3,3),TEMP,N); Inc (Y,1900); LYR := (Y mod 4 = 0) and (Y <> 1900); Dec (Y,1900); N := 0; StoP := False; While not StoP and (TDays[LYR][N] < TEMP) do Inc (N); M := N; { month } D := TEMP-TDays[LYR][M-1]; { subtract # days thru this month } Str(Y:2,SW); Str(M:2,ST); if ST[1] = ' ' then ST[1] := '0'; SW := SW ST; Str(D:2,ST); if ST[1] = ' ' then ST[1] := '0'; SW := SW ST; Dateord := SW end; { Dateord } end. { Unit TCDate }~~~Delphi K.Top討論區站長~~~
------
~~~Delphi K.Top討論區站長~~~ |
領航天使
站長 ![]() ![]() ![]() ![]() ![]() ![]() 發表:12216 回覆:4186 積分:4084 註冊:2001-07-25 發送簡訊給我 |
【文章】如何知道檔案是否被其他程式存取中?
【作者】hagar
【內文】來源:http://delphi.ktop.com.tw/topic.php?topic_id=37666 問題如下:
我開一個A程式,裡面有個Multi Thread來監看底下的一個子目錄,一但此子目錄有檔案,則呼叫一個副程式來讀檔,但現在問題來了,那個副程式只知道有檔案在此目錄下(使用FindFile的方式),但卻不知道此檔案是否已經讀寫完畢了,這樣就會發生,檔案還未存取完畢,副程式就已經讀檔完成,變成副程式讀的檔(文字檔)是不完全的,請問這要怎麼實作才會比較好? dllee回答如下:
hagar 版主所用的方法就是開檔而已,在 Windows 的開檔方式中德的 AccessMode 設定可以設定檔案是否可以被同時存取,或是只允許可以讓別人同時讀,或只允許別人寫但不能讀,或是完全不允許別人可以讀寫。
而判斷一個檔是否已經被使用但沒有關閉,就是對那個檔案作「開檔」的動作,同時指定 AccessMode 是別人不可以讀也不可以寫,只有我可以讀也可以寫。這樣,當這個檔案可以正常開啟時,就表示沒有其他函式在使用,如果有其他函式在使用,則會傳回 INVALID_HANDLE_VALUE 表示開檔不成功!當然開檔不成功也有可能是檔案本來就不存在,所以 hagar 版主在一開始就有判斷檔案存不存在。 其實,解決的方法有很多種,因為您把問題指定檔案是否處理完成,所以我想 hagar 版主的方式就可以解決。
如果所有的程式都是您自己開發,則問題可以是兩個(以上)的程式或執行緒之間資料、訊息交換的問題,在此您只需在處理檔案的執行緒或程式在處理檔案是發一個訊息給其他模組去收,或將一個旗標打開讓別人可以存取,例如另開一個檔案作資料交換或用
■【發表】跨行程共享記憶體 - Memory mapping file
http://delphi.ktop.com.tw/topic.php?TOPIC_ID=37041
或
■【Delphi】【分享】ShareMemRep 1.0 - 最佳的共享內存管理器替代方案
http://delphi.ktop.com.tw/topic.php?TOPIC_ID=35228
都可以。等處理檔案的執行緒處理完檔案,再以同樣的方式通知其他模組。
這樣,就不需要以「開檔」的方式來判斷檔是是否已處理完畢。 程式範例
function IsFileInUse(FileName: TFileName): Boolean; var HFileRes: HFILE; begin Result := False; if not FileExists(FileName) then Exit; HFileRes := CreateFile(PChar(FileName), GENERIC_READ or GENERIC_WRITE, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); Result := (HFileRes = INVALID_HANDLE_VALUE); if not Result then CloseHandle(HFileRes); end;
------
~~~Delphi K.Top討論區站長~~~ |
領航天使
站長 ![]() ![]() ![]() ![]() ![]() ![]() 發表:12216 回覆:4186 積分:4084 註冊:2001-07-25 發送簡訊給我 |
【文章】如何讓DBGRID的各欄位自動調整寬度?
【作者】pedro
【內文】來源:http://delphi.ktop.com.tw/topic.php?topic_id=44580 DBGrid的各Column的Width其實是由DataSet的欄位DisplayWidth帶出來的,
而這個DisplayWidth值是由資料庫的Schema定義欄位大小時給的, 例如整數是4.
如果資料表的欄位數很多, 一般都會超過DBGrid可視範圍. 所以說, DBGrid的Column寬度由資料表定義決定.
但是若您想用程式碼調整
下面片段程式碼您可以參考看看
var TotalGridDisplayWidth:Integer; procedure TForm1.FormCreate(Sender: TObject); var i:Integer; x:double; begin TotalGridDisplayWidth:=0; for i:=0 to DBGrid1.Columns.Count-1 do begin TotalGridDisplayWidth:=TotalGridDisplayWidth DBGrid1.Columns.Items[i].Width; end; for i:=0 to DBGrid1.Columns.Count-1 do begin x:=DBGrid1.Columns[i].Width / TotalGridDisplayWidth; DBGrid1.Columns[i].Width:=Round((DBGrid1.Width-50)*x); end; end;
------
~~~Delphi K.Top討論區站長~~~ |
領航天使
站長 ![]() ![]() ![]() ![]() ![]() ![]() 發表:12216 回覆:4186 積分:4084 註冊:2001-07-25 發送簡訊給我 |
【文章】如何傳網址給已開啟的IE?
【作者】qoo1234
【內文】來源:http://delphi.ktop.com.tw/topic.php?topic_id=45284
Q:
我已將IE開啟,但是每次Delphi程式被執行時需傳送不同網址給IE,1.如何得知IE已開啟,且將網址傳入IE重新更新?
A:
//傳網址給IE網址列
procedure TForm1.Button1Click(Sender: TObject); var IE,toolbar,combo,comboboxex,edit,worker,toolbarwindow: HWND; begin IE := FindWindow('IEFrame', nil); worker := FindWindowEx(IE,0,'WorkerW',nil); //注意版本差異 (有些用WorkerA) toolbar := FindWindowEx(worker,0,'reBarwindow32',nil); comboboxex := FindWindowEx(toolbar, 0, 'comboboxex32', nil); combo := FindWindowEx(comboboxex,0,'ComboBox',nil); edit := FindWindowEx(combo,0,'Edit',nil); toolbarwindow := FindWindowEx(comboboxex, 0, 'toolbarwindow32', nil); if IE <> 0 then begin SendMessage(edit , WM_SETTEXT, 0, Integer(PChar('http://delphi.ktop.com.tw'))); end else ShowMessage('IE瀏覽器不存在'); end;
------
~~~Delphi K.Top討論區站長~~~ |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |