Delphi常用技巧 3

Delphi常用技巧 3

**********************************
判断程序是否运行
if FindWindow(
主程序窗体类,主程序窗体标题) = 0 then //找到这个程序
begin
ShowMessage('
主程序没有运行') ;
Application.Terminate ;
end;


*******************************
得到鼠标位置上的类

procedure TForm1.Timer1Timer(Sender: TObject);
var
ClassName: PChar;
atCursor: TPoint;
hWndMouseOver: HWND;//
鼠标的句柄
Text: PChar;
begin
GetCursorPos(atCursor);//
得到鼠标坐标
hWndMouseOver:=WindowFromPoint(atCursor);//
得到鼠标句柄和位置
GetMem(ClassName, 100);
GetMem(Text, 255);
try
GetClassName(hWndMouseOver, ClassName, 100);
SendMessage(hWndMouseOver, WM_GETTEXT, 255, LongInt(Text));
Label_ClassName.Caption:='
类名(Classname) '+String(ClassName);
Edit1.Text:=String(Text);
finally
FreeMem(ClassName);
FreeMem(Text);
end;
end;


*****************************
实现断点续传

如果使用ICS控件,那么
HttpCli.ContentRangeBegin := '100'
表示从100开始
HttpCli.ContentRangeEnd :=''
表示一直到结束
HttpCli.ContentRangeEnd :='200'
表示到200字节处结束

如果使用 TNMHTTP 控件
OnAboutToSend事件,写:
NMHTTP1.SendHeader.values['Range'] := 'bytes=100-'
表示从100字节处开始下载到最后
NMHTTP1.SendHeader.values['Range'] := 'bytes=100-200'
表示从100字节处开始下载到200字节处结束
***************
procedure TForm1.Button6Click(Sender: TObject);
var
f:TSearchRec;
begin
FindFirst('a.doc',faAnyFile,f);
fPreSize:=f.Size;
NMFtp.DoCommand('Rest '+IntToStr(fPreSize));
NMFtp.DownloadRestore('a.doc','a.doc');
end;
这是用TNMFtp来续传的代码。

**********************************
Delphi
中用Sender参数实现代码重用

面向对象的编程工具的特点之一就是要提高代码重用性(Reuse),作为新一代可视化开发工具,Delphi中的代码重用性相当高。我们知道,在Delphi中,大部分程序代码都直接或间接地对应着一个事件,此程序称为事件处理句柄,它实际上就是一个过程。从应用程序的工程到表单、构件和程序,Delphi强调的是其开发过程中每一层次的重用性,可以通过编写某些构件常用的事件处理句柄来达到程序重用目的。你可以在属性窗口的Events页上将A事件的处理句柄指向B事件的处理句柄,这样A事件和B事件就共享了一个过程段,从而达到了重用的目的。如果共享的程序段与发生该事件的控件无关,如ShowMessage(′hello,world′),那这种共享是最简单的。但一般来说,代码段间的共享都跟发生该事件的控件有关,需要根据控件类型做出相应的处理,这时就要用到Sender参数。
  每个过程段的开头都类似procedure TForm1FormClick(Sender:TObject);其中的Sender是一个TObject类型的参数,它告诉Delphi哪个控件接收这个事件并调用相应的处理过程。你可以编写一个单一的事件处理句柄,通过Sender参数和IF…THEN…语句或者CASE语句配合,来处理多个构件。发生事件的构件或控件的值已经赋给了Sender参数,该参数的用途之一就在于:可以使用保留字IS来测试Sender,以便找到调用这个事件处理句柄的构件或控件的类型。例如,将表单中编辑框和标签的Click事件的处理句柄都指向表单的xxx过程,编辑框和标签对Click事件有不同的反应:
  procedure TForm1xxx(Sender:TObject);
  begin
  if(sender if Tedit) then
  showmessage(′this is a editbox′);
  if(sender is Tlabel) then
  showmessage(′this is a label′);
  end;
  Sender参数的第二个用途是结合AS操作符进行类型转换,将若干个派生于某一父类的子类强制转换成该父类。例如表单中有一个TEdit类控件和一个TMemo控件,它们实际上都派生于TcustomEdit类,如果你要为二者的某一事件提供同样处理,可以将二者事件句柄都指向自定义的过程yyy:
  Procedure TForm1.yyy(Sender:TObject);
  begin
  (sender as TcustomEdit).text:=′This is some demo text′;
  end;
  在过程中,AS操作符将TEdit类和TMemo类均强制转换成TcustomEdit类,再对TcustomEdit类的属性赋值。注意这种转换必须符合Delphi中类的层次关系。
  使用Sender参数可以通过单一过程段处理多类控件,真正体现了Delphi面向对象的重用性。

*****************************
窗口渐渐出现
AnimateWindow(Handle,1000,AW_CENTER);

*****************************
delphi
中嵌入汇编的方法

function cyclecount:int64;
asm
db $0f
db $31
end;


**********************
BIOS名称日期序列号
BIOS名称日期序列号,这个程序最短!在D5中测试通过!
with Memo1.Lines do
begin
Add('MainBoardBiosName:'+^I+string(Pchar(Ptr($FE061))));
Add('MainBoardBiosCopyRight:'+^I+string(Pchar(Ptr($FE091))));
Add('MainBoardBiosDate:'+^I+string(Pchar(Ptr($FFFF5))));
Add('MainBoardBiosSerialNo:'+^I+string(Pchar(Ptr($FEC71))));
end;

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

读主板信息:
主板名称: String(PChar(Ptr($FE061)));
版权: String(PChar(Ptr($FE091)));
日期: String(PChar(Ptr($FFFF5)));
序列号: String(PChar(Ptr($FEC71)));


***********************
20000下关机
20000下关机不象在98下直接调用ExitWindows函数就成,你首先要用OpenProcessToken函数打开与进程相关的访问信令然后再使用ExitWindow函数退出Win2000.

以下这段程序可供参考:
var
hToken :THandle ;
tkp :TOKEN_PRIVILEGES ;
otkp :TOKEN_PRIVILEGES ;
dwLen :Dword ;
begin
if OpenProcessToken(GetCurrentProcess ,TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY ,hToken) then
begin
LookupPrivilegevalue(Nil ,'SeShutdownPrivilege' ,tkp.Privileges[0].Luid) ;
tkp.PrivilegeCount := 1 ;
tkp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken ,False ,tkp ,sizeof(tkp) ,otkp,dwLen) ;
if (GetLastError() = ERROR_SUCCESS) then
begin
ExitWindowsEx(EWX_POWEROFF ,0) ; //
关机
end ;
end ;
end;


***************************
模拟键盘击键
shift + 'a'
换成Delphi 就是:

keybd_event(VK_SHIFT,0,KEYEVENTF_EXTENDEDKEY + 0,0);
keybd_event(65,0,KEYEVENTF_EXTENDEDKEY + 0,0);
keybd_event(65,0,KEYEVENTF_EXTENDEDKEY + KEYEVENTF_KEYUP,0);
keybd_event(VK_SHIFT,0,KEYEVENTF_EXTENDEDKEY + KEYEVENTF_KEYUP,0);

*****************************
弹出、关闭光驱
uses
中加MMSYSTEM

弹出光驱
mciSendString('Set cdaudio door open wait', nil, 0, handle);
关闭光驱
mciSendString('Set cdaudio door closed wait', nil, 0, handle);

*******************************
防止对话框ALT+F4关闭
TForm1 = class(TForm)
...
private
procedure WMSysCommand(var Msg: TWMSysCommand); message WM_SYSCOMMAND;
...
end;

procedure TForm1.WMSysCommand(var Msg: TWMSysCommand);
begin
if Msg.CmdType <> SC_CLOSE then
inherited
end;


*********************************
调用Windows内核
对程序员而言,有一句至理名言就是:写得好就是写得少!(Writing better is writing less)”
回答:
以下命令可以直接在Windows的运行窗口直接执行,在Delphi中你要这样使用:
winexec(Pchar('ABCD'),sw_Show);
其中"ABCD"代表以下命令之一:
"rundll32 shell32,Control_RunDLL" -
运行控制面板
"rundll32 shell32,OpenAs_RunDLL" -
打开"打开方式"窗口
"rundll32 shell32,ShellAboutA Info-Box" -
打开"关于"窗口
"rundll32 shell32,Control_RunDLL desk.cpl" -
打开"显示属性"窗口
"rundll32 user,cascadechildwindows" -
层叠全部窗口
"rundll32 user,tilechildwindows" -
最小化所有的子窗口
"rundll32 user,repaintscreen" -
刷新桌面
"rundll32 shell,shellexecute Explorer" -
重新运行Windows Explorer
"rundll32 keyboard,disable" -
锁写键盘
"rundll32 mouse,disable" -
让鼠标失效
"rundll32 user,swapmousebutton" -
交换鼠标按钮
"rundll32 user,setcursorpos" -
设置鼠标位置为(0,0)
"rundll32 user,wnetconnectdialog" -
打开"映射网络驱动器"窗口
"rundll32 user,wnetdisconnectdialog" -
打开"断开网络驱动器"窗口
"rundll32 user,disableoemlayer" -
显示BSOD窗口, (BSOD) = Blue Screen Of Death, 即蓝屏
"rundll32 diskcopy,DiskCopyRunDll" -
打开磁盘复制窗口
"rundll32 rnaui.dll,RnaWizard" -
运行"Internet连接向导", 如果加上参数"/1"则为silent模式
"rundll32 shell32,SHFormatDrive" -
打开"格式化磁盘(A)"窗口
"rundll32 shell32,SHExitWindowsEx -1" -
冷启动Windows Explorer
"rundll32 shell32,SHExitWindowsEx 1" -
关机
"rundll32 shell32,SHExitWindowsEx 0" -
退当前用户
"rundll32 shell32,SHExitWindowsEx 2" Windows9x
快速重启
"rundll32 krnl386.exe,exitkernel" -
强行退出Windows 9x(无确认)
"rundll rnaui.dll,RnaDial "MyConnect" -
运行"网络连接"对话框
"rundll32 msprint2.dll,RUNDLL_PrintTestPage" -
选择打印机和打印测试页
"rundll32 user,setcaretblinktime" -
设置光标闪烁速度
"rundll32 user, setdoubleclicktime" -
测试鼠标双击速度
"rundll32 sysdm.cpl,InstallDevice_Rundll" -
搜索非PnP设备

***********************************
messagebeep(0);//
声卡发出be
windows.beep(2000,2000);//pc
喇叭发出be声,很吓人//前一个是频率,后一个是延时,98下会忽略

*******************************************************
得到可用内存和系统资源
procedure Tversion.FormCreate(Sender: TObject);
var
MS: TMemoryStatus;
begin
GlobalMemoryStatus(MS);
label5.Caption := '
可用内存:'+FormatFloat('#,###" KB"', MS.dwTotalPhys / 1024);
label6.Caption := '
系统资源 '+Format('%d %%', [MS.dwMemoryLoad])+' 可用';
end;


*****************************************************
检查程序是否无响映
function IsBusy(ProcessId: Integer): Integer;
var
Ph: THandle;
begin
Ph := OpenProcess(PROCESS_ALL_ACCESS, false, ProcessId);
if Ph <> 0 then
begin
if WaitForInputIdle(Ph, 10) = WAIT_TIMEOUT then
Result := 1
else
Result := 0;
CloseHandle(Ph);
end
else Result := -1;
end;


******************************
琐住鼠标 + 琐住键盘
-*******-*-*****************

var a:TRect;
temp:integer;
begin
{
屏蔽系统键}
SystemParametersInfo( SPI_SCREENSAVERRUNNING, 1, @temp, 0);
a:=rect(0,0,5,5);
{
锁定鼠标在一定区域内,最好锁在你的窗口里}
ClipCursor(@a);
end;
{
解除锁定}
begin
SystemParametersInfo( SPI_SCREENSAVERRUNNING, 0, @temp, 0);
ClipCursor(nil);
end;


******************************
copy
屏幕
-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
procedure TForm1.Button1Click(Sender: TObject);
var
dc:hdc;
mycanvas:TCanVas;
mybitmap:TBitmap;
begin
application.Minimize;
mycanvas:=TCanvas.Create;
mybitmap:=tbitmap.Create;
dc:=getdc(0);
try
myCanvas.Handle := DC;
with Screen do
begin
MyBitmap.Width := Width;
MyBitmap.Height := Height;
MyBitmap.Canvas.CopyRect(Rect(0,0,Width,Height),myCanvas,Rect(0,0,Width,Height));
image1.Picture.Bitmap.Assign(mybitmap);
end;
finally
releasedc(0,dc);
mycanvas.Free;
mybitmap.Free;
end;
application.Restore;
end;


***************************
ACCESS
技巧集
作者:ysai
转载请保持文章完整并标明出处

1.DELPHI
中操作ACCESS数据库(建立.mdb文件,压缩数据库)
以下代码在WIN2K,D6,MDAC2.6下测试通过,
编译好的程序在WIN98第二版无ACCESS环境下运行成功.
//
声明连接字符串
Const
SConnectionString = 'Provider=Microsoft.Jet.OLEDB.4.0;Data Source=%s;'
+'Jet OLEDB:Database Password=%s;';

//=============================================================================
// Procedure: GetTempPathFileName
// Author : ysai
// Date : 2003-01-27
// Arguments: (None)
// Result : string
//=============================================================================
function GetTempPathFileName():string;
//
取得临时文件名
var
SPath,SFile:array [0..254] of char;
begin
GetTempPath(254,SPath);
GetTempFileName(SPath,'~SM',0,SFile);
result:=SFile;
DeleteFile(result);
end;

//=============================================================================
// Procedure: CreateAccessFile
// Author : ysai
// Date : 2003-01-27
// Arguments: FileName:String;PassWord:string=''
// Result : boolean
//=============================================================================
function CreateAccessFile(FileName:String;PassWord:string=''):boolean;
//
建立Access文件,如果文件存在则失败
var
STempFileName:string;
vCatalog:OleVariant;
begin
STempFileName:=GetTempPathFileName;
try
vCatalog:=CreateOleObject('ADOX.Catalog');
vCatalog.Create(format(SConnectionString,[STempFileName,PassWord]));
result:=CopyFile(PChar(STempFileName),PChar(FileName),True);
DeleteFile(STempFileName);
except
result:=false;
end;
end;

//=============================================================================
// Procedure: CompactDatabase
// Author : ysai
// Date : 2003-01-27
// Arguments: AFileName,APassWord:string
// Result : boolean
//=============================================================================
function CompactDatabase(AFileName,APassWord:string):boolean;
//
压缩与修复数据库,覆盖源文件
var
STempFileName:string;
vJE:OleVariant;
begin
STempFileName:=GetTempPathFileName;
try
vJE:=CreateOleObject('JRO.JetEngine');
vJE.CompactDatabase(format(SConnectionString,[AFileName,APassWord]),
format(SConnectionString,[STempFileName,APassWord]));
result:=CopyFile(PChar(STempFileName),PChar(AFileName),false);
DeleteFile(STempFileName);
except
result:=false;
end;
end;

2.ACCESS
中使用SQL语句应注意的地方及几点技巧
以下SQL语句在ACCESS XP的查询中测试通过
建表:
Create Table Tab1 (
ID Counter,
Name string,
Age integer,
[Date] DateTime);
技巧:
自增字段用 Counter 声明.
字段名为关键字的字段用方括号[]括起来,数字作为字段名也可行.

建立索引:
下面的语句在Tab1Date列上建立可重复索引
Create Index iDate ON Tab1 ([Date]);
完成后ACCESS中字段Date索引属性显示为 - (有重复).
下面的语句在Tab1Name列上建立不可重复索引
Create Unique Index iName ON Tab1 (Name);
完成后ACCESS中字段Name索引属性显示为 - (无重复).

ACCESS
SQLSERVER中的UPDATE语句对比:
SQLSERVER
中更新多表的UPDATE语句:
UPDATE Tab1
SET a.Name = b.Name
FROM Tab1 a,Tab2 b
WHERE a.ID = b.ID;
同样功能的SQL语句在ACCESS中应该是
UPDATE Tab1 a,Tab2 b
SET a.Name = b.Name
WHERE a.ID = b.ID;
:ACCESS中的UPDATE语句没有FROM子句,所有引用的表都列在UPDATE关键字后.
上例中如果Tab2可以不是一个表,而是一个查询,:
UPDATE Tab1 a,(Select ID,Name From Tab2) b
SET a.Name = b.Name
WHERE a.ID = b.ID;

访问多个不同的ACCESS数据库-SQL中使用In子句:
Select a.*,b.* From Tab1 a,Tab2 b In 'db2.mdb' Where a.ID=b.ID;
上面的SQL语句查询出当前数据库中Tab1db2.mdb(当前文件夹中)Tab2ID为关联的所有记录.
缺点-外部数据库不能带密码.

ACCESS中访问其它ODBC数据源
下例在ACCESS中查询SQLSERVER中的数据
SELECT * FROM Tab1 IN [ODBC]
[ODBC;Driver=SQL Server;UID=sa;PWD=;Server=127.0.0.1;DataBase=Demo;]
外部数据源连接属性的完整参数是:
[ODBC;DRIVER=driver;SERVER=server;DATABASE=database;UID=user;PWD=password;]
其中的DRIVER=driver可以在注册表中的
HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBCINST.INI\
中找到

ACCESS
支持子查询

ACCESS
支持外连接,但不包括完整外部联接,如支持
LEFT JOIN
RIGHT JOIN
但不支持
FULL OUTER JOIN
FULL JOIN

ACCESS
中的日期查询
注意:ACCESS中的日期时间分隔符是#而不是引号
Select * From Tab1 Where [Date]>#2002-1-1#;
DELPHI中我这样用
SQL.Add(Format(
'Select * From Tab1 Where [Date]>#%s#;',
[DateToStr(Date)]));

 

技巧四

问:模拟键盘

最近碰到使用 SendMessage PostMessage 機會超級多,無非是因為太多的專案需求,如果耗費人力全部自行開發,大概請二、三倍的人力結果也只是為了完成幾個對於圖形處理的動作而已,因此購買已經寫好的軟體直接使用就行,但畢竟購買是購買,有些畫面或是需求畢竟是套裝軟體無法達成的,於是還是得自己寫控制指令

可以自己寫一個類似按鍵精靈的東東,也就是控制滑鼠自動在畫面上操作東西

滑鼠自動點擊的例子

procedure TForm1.Button1Click(Sender: TObject);

var x,y:integer;

begin

    x:= form1.Left+button2.Left+25;

    y:= top+button2.Top+27;

    SetCursorPos(x,y);   // 移到某個點

    Mouse_Event(MOUSEEVENTF_LEFTDOWN,X,Y,0,0); // 按下滑鼠左鍵

    Mouse_Event(MOUSEEVENTF_LEFTUP,X,Y,0,0);   // 放開左鍵

end;

 

procedure TForm1.Button2Click(Sender: TObject);

begin

 showmessage('fksj');

end;

*************************************

其中 mouse_event 這是 WindowsAPI 的指令,

還有下列的幾種

MOUSEEVENTF_MOVE            = $0001; { mouse move }

MOUSEEVENTF_LEFTDOWN        = $0002; { left button down }

MOUSEEVENTF_LEFTUP          = $0004; { left button up }

MOUSEEVENTF_RIGHTDOWN       = $0008; { right button down }

MOUSEEVENTF_RIGHTUP         = $0010; { right button up }

MOUSEEVENTF_MIDDLEDOWN      = $0020; { middle button down }

MOUSEEVENTF_MIDDLEUP        = $0040; { middle button up }

MOUSEEVENTF_WHEEL           = $0800; { wheel button rolled }

MOUSEEVENTF_ABSOLUTE        = $8000; { absolute move }

而下面的這段則是模擬鍵盤

//Ctrl+C: 
keybd_event(VK_CONTROL, MapVirtualKey(VK_CONTROL, 0), 0, 0); 
keybd_event(Ord('C'), MapVirtualKey(Ord('C'), 0), 0, 0); 
keybd_event(Ord('C'), MapVirtualKey(Ord('C'), 0), KEYEVENTF_KEYUP, 0); 
keybd_event(VK_CONTROL, MapVirtualKey(VK_CONTROL, 0), KEYEVENTF_KEYUP, 0) 
 
//Ctrl+V: 
keybd_event(VK_CONTROL, MapVirtualKey(VK_CONTROL, 0), 0, 0); 
keybd_event(Ord('V'), MapVirtualKey(Ord('V'), 0), 0, 0); 
keybd_event(Ord('V'), MapVirtualKey(Ord('V'), 0), KEYEVENTF_KEYUP, 0); 
keybd_event(VK_CONTROL, MapVirtualKey(VK_CONTROL, 0), KEYEVENTF_KEYUP, 0) 

问:Delphi中设置默认打印机

type
  TForm1 = class(TForm)
    Button1: TButton;
    ComboBox1: TComboBox;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }   
  public
    { Public declarations }
  end;

{...}

procedure TForm1.FormCreate(Sender: TObject);
begin
  { tell printer to go to the default by setting
    the PrinterIndex value to -1 }
  Printer.PrinterIndex := -1;

  { make our combobox non-editable }
  ComboBox1.Style      := csDropDownList;

  { set our combobox items to the printer printers }
  ComboBox1.Items      := Printer.Printers;

  { set combobox to view the default printer
    according to printer printerindex as set above }
  ComboBox1.ItemIndex  := Printer.PrinterIndex;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  MyHandle  : THandle;
  MyDevice,
  MyDriver,
  MyPort: array [0..255] of Char;
begin
  { set printer to the selected according to the
    combobox itemendex }
  Printer.PrinterIndex := ComboBox1.ItemIndex;

  { get our printer properties }
  Printer.GetPrinter(MyDevice,
                     MyDriver,
                     MyPort,
                     MyHandle);

  { create string of exactly what WriteProfileString()
    wants to see by concat each of the above received
    character arrays }
  StrCat( MyDevice, ',');
  StrCat( MyDevice, MyDriver );
  StrCat( MyDevice, ',');
  StrCat( MyDevice, MyPort );

  { copy our new default printer into our windows ini file
    to the [WINDOWS] section under DEVICE= }
  WriteProfileString('WINDOWS',
                     'DEVICE',
                     MyDevice );

  { tell all applications that the windows ini file has
    changed, this will cause them all to recheck default
    printer }
  SendMessage(HWND_BROADCAST,
              WM_WININICHANGE,
              0,
              LongInt(pChar('windows')));
  end;
end;

 

原文地址:https://www.cnblogs.com/hssbsw/p/1953845.html