主题:[资料]Windows API
progfan
[专家分:2270] 发布于 2006-04-14 21:47:00
GetTickCount——返回Windows系统启动后运行的时间(毫秒数)
回复列表 (共4个回复)
沙发
progfan [专家分:2270] 发布于 2006-04-14 21:50:00
procedure TForm1.Timer1Timer(Sender: TObject);
var
hour,minute,second:integer;
begin
hour:=gettickcount div (1000*60*60);
minute:=(gettickcount-hour*1000*60*60) div (1000*60);
second:=(gettickcount-hour*1000*60*60-minute*1000*60) div 1000;
edit1.Text:='系统启动已经'+inttostr(hour)+'小时'+inttostr(minute)+'分'+inttostr(second)+'秒';
end;
板凳
progfan [专家分:2270] 发布于 2006-05-27 23:30:00
FindWindow(ByVal lpClassName As String, ByVal lpWindowName As String) As Long
这个函数有两个参数,第一个是要找的窗口的类,第二个是要找的窗口的标题。在搜索的时候不一定两者都知道,但至少要知道其中的一个。
如果你知道该窗口的类名或标题,可以直接将类名或标题代入下面的FindWindow函数中,
下面的代码首先查找目标窗口的句柄,再枚举该窗口的子窗口,判断子窗口的类名是否
为"Edit"或"TEdit",若是,则认为已经找到编缉框。找到后,再发送WM_GETTEXTLENGTH
和WM_GETTEXT消息来获取编缉框的文本长度及内容。
var
hwndEdit:THandle;
function EnumWindowProc(hwnd:THandle;lParam:LPARAM):BOOL;stdcall;
var
ClassName:array[0..255] of Char;
begin
Result:=True;
if GetClassName(hwnd,ClassName,256)>0 then
if SameText(ClassName,'TEdit') or SameText(ClassName,'Edit') then
begin
Result:=False;
hwndEdit:=hwnd;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
hWin:THandle;
buf:string;
iLen:Integer;
begin
hwndEdit:=0;
hWin:=FindWindow('TRegFrm',nil);
if hWin<>0 then
begin
EnumChildWindows(hWin,@EnumWindowProc,0);
end;
if hwndEdit>0 then
begin
iLen:=SendMessage(hwndEdit,WM_GETTEXTLENGTH,0,0);
SetLength(buf,iLen+1);
GetWindowText(hwndEdit,PChar(@buf[1]),iLen+1);
ShowMessage(buf);
end;
end;
//附:如果你不知道目标窗口的类名,那么请在窗口上放一个TTimer,一个TEdit
在OnTimer事件中写如下代码,编译执行后将Mouse移到目标窗口上,目标窗口的
类名则会显示在TEdit上。
procedure TForm1.Timer1Timer(Sender: TObject);
var
p:TPoint;
hwnd:THandle;
ClassName:array[0..255] of Char;
begin
GetCursorPos(p);
hwnd:=WindowFromPoint(p);
if hwnd<>0 then
begin
GetClassName(hwnd,ClassName,256);
Edit1.Text:=ClassName
end;
end;
来自:linp, 时间:2006-4-11 11:11:35, ID:3410939
smokingroom大哥,再求助一下,我看了一下是ListBox编辑框,请问怎样读取?如果有多个EDIT框时怎样移到下一个EDIT框读取数据?谢谢!
1、如果是ComboBox,那么将
if SameText(ClassName,'TEdit') or SameText(ClassName,'Edit') then
改为
if SameText(ClassName,'TComboBox') or SameText(ClassName,'COMBOBOX') then
最好使用上面附带的方法查看一下它的类名。一般情况下为COMBOBOX或TComboBox
2、
如果是多个编缉框,可以修改一下上面的代码:
function EnumWindowProc(hwnd:THandle;lParam:LPARAM):BOOL;stdcall;
var
ClassName:array[0..255] of Char;
buf:string;
iLen:Integer;
begin
Result:=True;
if GetClassName(hwnd,ClassName,256)>0 then
if SameText(ClassName,'TComboBox') or SameText(ClassName,'COMBOBOX') then
begin
iLen:=SendMessage(hwnd,WM_GETTEXTLENGTH,0,0);
SetLength(buf,iLen+1);
GetWindowText(hwnd,PChar(@buf[1]),iLen+1);
ShowMessage(buf);
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
hWin:THandle;
begin
hwndEdit:=0;
hWin:=FindWindow('TRegFrm',nil);
if hWin<>0 then
EnumChildWindows(hWin,@EnumWindowProc,0);
end;
来自:linp, 时间:2006-4-11 14:49:31, ID:3411278
谢谢smokingroom大哥,我用你提供的方式测试了,是“Static”、"Edit"和"ListBox",“Static”和"Edit"可以取出数据来,但ListBox中的数据无法取出,再次麻烦你,请问ListBox中的数据怎样取出来?
来自:smokingroom, 时间:2006-4-11 15:31:43, ID:3411333
LISTBOX处理方法不一样,需要一条一条地读取。
var
iCount,iLen,I:Integer;
retStr:string;
buf:string;
begin
retStr:='';
iCount:=SendMessage(hwnd,LB_GETCOUNT,0,0);
for I:=0 to iCount-1 do
begin
iLen:=SendMessage(hwnd,LB_GETTEXTLEN,0,0);
SetLength(buf,iLen+1);
SendMessage(hwnd,LB_GETTEXT,I,Integer(@buf[1]));
retStr:=retStr+Trim(buf)+#13#10;
end;
ShowMessage(retStr);
end;
3 楼
progfan [专家分:2270] 发布于 2006-05-27 23:33:00
有三个API函数可以运行可执行文件WinExec、ShellExecute和CreateProcess。CreateProcess因为使用复杂,比较少用。
WinExec主要运行EXE文件。如:WinExec('Notepad.exe Readme.txt', SW_SHOW);
ShellExecute不仅可以运行EXE文件,也可以运行已经关联的文件。
首先必须引用shellapi.pas单元:uses ShellAPI;
1.标准用法
ShellExecute函数原型及参数含义如下:
function ShellExecute(hWnd: HWND; Operation, FileName, Parameters,Directory: PChar; ShowCmd: Integer): HINST; stdcall;
●hWnd:用于指定父窗口句柄。当函数调用过程出现错误时,它将作为Windows消息窗口的父窗口。例如,可以将其设置为应用程序主窗口句柄,即Application.Handle,也可以将其设置为桌面窗口句柄(用GetDesktopWindow函数获得)。
●Operation:用于指定要进行的操作。其中“open”操作表示执行由FileName参数指定的程序,或打开由FileName参数指定的文件或文件夹;“print”操作表示打印由FileName参数指定的文件;“explore”操作表示浏览由FileName参数指定的文件夹。当参数设为nil时,表示执行默认操作“open”。
●FileName:用于指定要打开的文件名、要执行的程序文件名或要浏览的文件夹名。
●Parameters:若FileName参数是一个可执行程序,则此参数指定命令行参数,否则此参数应为nil或PChar(0)。
●Directory:用于指定默认目录。
●ShowCmd:若FileName参数是一个可执行程序,则此参数指定程序窗口的初始显示方式,否则此参数应设置为0。
若ShellExecute函数调用成功,则返回值为被执行程序的实例句柄。若返回值小于32,则表示出现错误。
上述仅仅是ShellExecute函数的标准用法,下面将介绍它的特殊用法。
2.特殊用法
如果将FileName参数设置为“http:”协议格式,那么该函数将打开默认浏览器并链接到指定的URL地址。若用户机器中安装了多个浏览器,则该函数将根据Windows 9x/NT注册表中http协议处理程序(Protocols Handler)的设置确定启动哪个浏览器。
格式一:http://网站域名。
如:ShellExecute(handle, ‘open’, http:// ;
www.neu.edu.cn’, nil, nil, SW_SHOWNORMAL);
格式二:http://网站域名/网页文件名。
如:ShellExecute(handle, ‘open’, http:// ;
www.neu.edu.cn/default.htm’,nil,nil,
SW_SHOWNORMAL);
如果将FileName参数设置为“mailto:”协议格式,那么该函数将启动默认邮件客户程序,如Microsoft Outlook(也包括Microsoft Outlook Express)或Netscape Messanger。若用户机器中安装了多个邮件客户程序,则该函数将根据Windows 9x/NT注册表中mailto协议处理程序的设置确定启动哪个邮件客户程序。
格式一:mailto:
如:ShellExecute(handle,‘open’, ‘mailto:’, nil, nil, SW_SHOWNORMAL);打开新邮件窗口。
格式二:mailto:用户账号@邮件服务器地址
如:ShellExecute(handle, ‘open’,‘ mailto:who@mail.neu.edu.cn’, nil, nil, SW_SHOWNORMAL);打开新邮件窗口,并自动填入收件人地址。若指定多个收件人地址,则收件人地址之间必须用分号或逗号分隔开(下同)。
格式三:mailto:用户账号@邮件服务器地址?subject=邮件主题&body=邮件正文
如:ShellExecute(handle, ‘open’, ‘ mailto:who@mail.neu.edu.cn?subject=Hello&Body=This is a test’, nil, nil, SW_SHOWNORMAL);打开新邮件窗口,并自动填入收件人地址、邮件主题和邮件正文。若邮件正文包括多行文本,则必须在每行文本之间加入换行转义字符%0a。
例子(delphi):
4 楼
progfan [专家分:2270] 发布于 2006-05-30 07:32:00
http://www.ddvip.com/program/vb/index1/103.htm
功能强大的SendMessage函数
作者:unknown 更新时间: 2005-04-30
Windows API(应用程序接口)是Windows系列软件为程序开发人员提供的火力强大的“武器库”,在这个武器库中,有很多极具威力的武器,SendMessage就是其中之一,它的功能非常丰富,灵活使用这个函数,会给编程工作带来很多便利。本文以Visual Basic为例,结合几个具体的例子介绍该函数的功能。
一、SendMeaasge函数简介
顾名思义,SendMessage函数的功能是“发送消息”,即将一条消息发送到指定对象(操作系统、窗口或控件等)上,以产生特定的动作(如滚屏、修改对象外观等)。
SendMessage函数在VB中的函数说明如下:
Declare Function SendMessage Lib "user32" Alias "SendMessageA" (Byval hwnd As Long, Byval wMsg As Long,Byval wParam As Long,lParam As Any) As Long
其中四个自变量的含义和说明如下:
hWnd:对象的句柄。希望将消息传送给哪个对象,就把该对象的句柄作为实参传送,在VB中可以简单地用“对象.hWnd”获得某个对象的句柄,如Text1.hWnd和Form1.hWnd分别可以得到Text1和Form1的句柄。
wMsg:被发送的消息。根据具体需求和不同的对象,将不同的消息作为实参传送,以产生预期的动作。
wParam、lParam:附加的消息信息。这两个是可选的参数,用来提供关于wMsg消息更多的信息,不同的wMsg可能使用这两个参数中的0、1或2个,如果不需要哪个附加参数,则将实参赋为NULL(在VB中赋为0)。
在简单了解了SendMessage函数的格式和功能后,让我们以几个例子来看看它的威力。
二、SendMessage函数使用实例
例1 多行TextBox中的快速处理功能在处理多行TextBox时我们经常会碰到以下几种情况:
希望了解多行TextBox中目前共有多少行文字。
想快速返回第N行的文字。
对于上面的情况,如果用VB自身的语句或函数来实现的话,要写不短的代码,而且由于要采用顺序查找的办法来完成,因此代码的执行效率也很低。如果使用SendMessage函数则可以大大减少代码量,并大幅度的提高执行效率。
用SendMessage函数完成上面两个任务的方法非常简单,每个任务只需简单地发送一条消息给多行TextBox即可,两个消息分别为:EM_GETLINECOUNT、EM_GETLINE,其它参数和返回值见附表。
下面用一个简单的实例演示这两个功能:
新建工程,在Form1上添加三个TextBox(名称分别为Text1、txtLineCount、TxtString,将Text1的Multi
Line属性置为True)、三个标签和一个命令按钮。为工程添加一个模块Moudle1,在其中写如下声明(其中
SendMessage函数的声明可以从VB的“API浏览器”中复制): 消息常量名 消息值 wParam lParam 返回值
EM_GETLINECOUNT &HBA 未用 未用 行数
EM_GETLINE &HC4 要找的行号 存结果的字节串 结果字节串的字节数
Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long,lParam As Any) As Long
Public Const EM_GETLINECOUNT=&HBA
Public Const EM_GETLINE=&HC4
在Form1的代码模块中写如下代码:
Private Sub Command1_Click()
Dim str(256) As Byte
str(1)=1 '最大允许存放256个字符
'获取总行数,结果显示在文本框txtLineCount中
txtlineCount=SendMessage(Text1.hwnd,EM_GETLINECOUNT,0,0)
'获取第3行的数据放在str中,转换为字符串后显示在文本框txtString中
SendMessage Text1.hwnd,EM_GETLINE,2,str(0)
txtString= StrConv(str,vbUnicode)
End Sub
之后,按F5运行程序,在多行文本框中随便键入几行文字,然后按下[确定]按钮,出现如图画面,说明程序正确统计出了总行数和第3行的文字。
两点补充说明:在调用SendMessage获取第N行字符串时,lParam需要说明为字节数组,在调用完成后,再将字节数组转换为字符串;另外,调用前必须在lParam的前两个字节指明允许存放的最大长度,其中第一个字节为低位,第二个字节为高位,本例将高位(即str(1))置1.说明最大允许存放256个字符。
例2 程序控制拉下或收起组合框的下拉列来
一般情况下,为了拉下或收起组合框的下拉列表,需要用键盘或鼠标进行操作,而有时我们希望程序运行的某个时刻自动拉出下拉列表(比如在一些演示程序中),为了实现这个目的,我们也只有借助于SendMessage函数,方法是发一个CB_SHOWDROPDOWN(&H14F)消息给组合框。
在发CB_SHOWDROPDOWN消息时,wParam参数决定了是拉下列表(=True时)还是收起列表(=False时),lParam无用(设为0)。
为说明具体的使用方法,下面提供简单的程序片段。首先在代码模块中做如下声明:
Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long,ByVal wMsg As Long,ByVal wParam As Long,lParam As Any) As Long
Const CB_SHOWDROPDOWN=&H14F
当程序中某处需要拉下组合框Combol的列表时,写如下调用语句:
SendMessage Combol.hwnd,CB_SHOWDROPDOWN,True,0
当需要收起组合框Combol的列表时,写如下语句:
SendMessage Combol.hwnd,CB_SHOWDROPDOWNN,False,0
例3 在列表框中查找匹配的项目
在Win95风格的帮助系统中一般都有一个“索引”页,索引页含有一个文本框和一个列表框,当用户在文本框中输入文字时,下拉列表会动态地显示与文本框中文字最匹配的项目,为用户提供了最大的方便。这种效果在应用程序的帮助系统中很容易实现(只要按照Win95帮助系统的正常制作过程制作就可以实现),如果想在应用程序的其它地方实现这种特性就需费一番心思了。
而使用SendMessage函数实现上述特性则非常简单,甚至只需一条语句就足够了,那就是在文本框的Change事件中给列表框发一条LB_FINDSTRING(&H18F)消息,该消息告诉列表框在列表中查找匹配的项目。
在发LB_FINDSTRING消息时,wParam参数代表从列表框的哪一个项目后面开始查找,一般情况下该参数可定为-1,表示从List1(0)即第一项开始向后循环查找,lParam则传进欲搜索的字符串(必须采用值传递)。
具体的代码和运行画面与后面的例4合并在一起演示。
例4 为ListBox添加水平滚动条
在VB中,列表框控件仅提供垂直滚动条,没有设置水平滚动条的能力,当某些项目的文本宽度较长时,超出列表框宽度部分的文本就无法显示出来,因此,很有必要为ListBox添加一个水平滚动条来方便操作。
为添加水平滚动条,只需发一条LB_SETHORIZONTALEXTENT(&H194)消息给列表框即可。发送消息时,wParam为滚动条的长度(以像素为单位,可通过计算得出准确的长度,也可随便给一个大于最大文本宽度的数字,如本例的250),lParam无用。下面是例3和例4合并在一起的代码和运行画面
Declare Function SendMessage Lib "user32" Alias "SendMessageA"(ByVal hwnd As Long,ByVal wMsg As Long,ByVal wParam As Long,lParam As Any) As Long
Public Const LB_FINDSTRING=&H18F
Public Const LB_SETHORIZONTALEXTENT=&H194
Private Sub Form_Load()
List1.AddItem "软件"
List1.AddItem "电脑游戏"
List1.AddItem "电视机"
List1.AddItem "电视台"
List1.AddItem "电脑"
List1.AddItem "电脑游戏软件"
'下一句为列表框添加水平滚动条
SendMessage List1.hwnd,LB_SETHORIZONTALEXTENT,250,0
End Sub
Private Sub Text1_Change()
'注意!当lParam传入的是字符串时,必须用ByVal传递
List1.ListIndex = SendMessage(List1.hwnd,LB_FINDSTRING,-1,ByVal Text1.Text)
End Sub
通过上面几个例子,想必您已经对SendMessage函数的强大功能有了初步的了解。事实上利用该函数我们还可以完成更多更好的任务,如控制文本框的自动滚屏、实现文字编辑过程中的Undo功能、操纵应用程序的窗体控制菜单等等,感兴趣的读者请参阅有关Windows API的资料。
本文程序均用Visual Basic 5.0企业版编写,在Pwin95环境下运行正常。
我来回复