举个例子,一个程序中有文本框,我想在另一个程序中不用‘cut’or'copy'的方式就获得其中的文字!或是他的一些其他信息? 急在线等待!
最好可以给个例子!分数不够可以再加!
最好可以给个例子!分数不够可以再加!
解决方案 »
- COPYDATA 接收问题
- 键值列数不足或不正确,更新影响到多行
- dbGrid如何实现如下东西?帮忙.
- 请高手看看这个问题~~~~
- 主从表的SQL语句该怎么写,谢谢?
- 如何在DBGRID的第一列,加上记录的编号呀。谢谢!!!
- 请问怎样才能在Delphi6中加入个GIF格式的动画?
- 关于API函数
- 有在北京的同行吗?请教几个非技术问题
- 在BDE里新建了MSSQL类型的别名,然后打开别名旁边的“+”,弹出对话框,要求输入用户名和密码,请问为什么?如何解决?谢了!
- 困惑!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!近来有了一种想自己写一套XP界面控件的想法,但网上已有有N多的XP界面控件了,我还有必要自己写一套
- 为什么没有ComboBox1.AddObject方法?
成批升级你的MP3
《电脑报》今年第四期(1月28日)上以“升级你的MP3”为题介绍了MP3Pro这一更好的音乐文件格式,笔者试着将一首MP3转为MP3Pro,发现音质几乎无损,文件大小却减少一半,而且新转换的.mp3文件也能被其他MP3播放器播放!这样的好事可不多见,我800多M的MP3可以减肥多少呀!MP3升级到MP3Pro之间要有wav文件作过渡,于是我用超级解霸2001的音频转换器一次将10首MP3转换为.wav文件,然后……问题就来了。MP3Pro播放器的转换工具(Encoder)一次只能转换一首歌曲,这样我要等待一曲转完后再手动设置,如此下来,上百首MP3的转换岂不是要把我累坏?能不能编程实现成批转换?
当然可以!下面请跟我来一步一步实现“MP3Pro成批转换助手”:
1. 到http://www.esoftware.com.cn下载MP3Pro播放器(
THOMSON mp3Pro Audio Player)。安装后执行它,单击encode按钮就可以看到如图1的界面,我们要做的事就是适时往两个edit控件(分别填入输入的wav文件目录和输出的mp3文件目录)中“填入”我们的文件路径,然后“按”一下encode按钮让它开始转换。这“填入”和“按”都要编程实现。
2. 思路分析:要控制mp3Pro转换器,首先要打开它,我用
FindWindow函数来查找是否存在名为“Thomson mp3Pro Encoder”的窗口。要往两个edit控件中填入文本和按encode按钮,可以调用SendDlgItemMessage向edit控件发送WM_SETTEXT消息及向按钮发送BM_CLICK消息。再设一个定时器,每隔10秒检查encode按钮上的文字,如果为“STOP”,则说明正在转换中,如果为“ENCODE”则可以继续进行下一首的转换,这时可以继续往edit控件中填入指定内容,然后按encode按钮。使用Spy++可以看出,填输入文件位置的edit控件ID为1000,填输出文件位置的edit控件ID为1001,按钮encode的ID为1013.
3. 有了思路,实现起来就方便了。下面是用Delphi实现上述思想的源代码(设计界面如图2): //按下“开始转换”按钮
procedure TForm1.Button1Click(Sender: TObject);
begin
count := 0;//编码计数器
theHwnd := FindWindow(nil,'Thomson mp3Pro Encoder');
//theHwnd为公有成员变量
if theHwnd <> null then
begin
StartTime := GetTickCount;
//公有成员变量StartTime记录开始时间
Perform;//核心所在哦,发送上述三个消息
Timer.Enabled := true
end
else
showmessage('没有发现MP3Pro Encoder');
end;//Timer控件的Interval属性设为10000,即10秒触发一次OnTimer
procedure TForm1.TimerTimer(Sender: TObject);
var str : array[0..9] of char;
Duration : integer; //记录所有编码完成的大概时间
begin
if (GetDlgItemText(theHwnd,1013,str,10) > 0) then
begin
if str = 'ENCODE' then
begin
if count = Total then
begin
Timer.enabled := false;
endTime := GetTickCount;
Duration := ( endTime - startTime ) div 1000;
MessageBeep(MB_OK); //鸣笛提示完成
showmessage('所有Wav文件编码完成!总计大约耗时:'+ InttoStr(Duration) + '秒');
end
else
Perform;// //为下一首wav编码
end;
end;
end;procedure TForm1.Perform();
begin
if theHwnd <> null then
begin
SendDlgItemMessage(theHwnd,1000,WM_SETTEXT,0, Integer(Pointer(Pchar(WavFiles.Items[count]))));
//将后缀改为.mp3后填入输出edit控件
SendDlgItemMessage(theHwnd,1001,WM_SETTEXT,0, Integer(Pointer(Pchar(ChangeFileExt(WavFiles.Items[count],‘.mp3')))));//WavFiles为TlistBox控件
SendDlgItemMessage(theHwnd,1013,BM_CLICK,0,0);
Inc(count);
label2.Caption := '现在正在为第'+InttoStr(count) +'个编码。';
end;
end;//按下了“选择wav文件”的按钮
{--------OpenDlg为TopenDialog控件,其options中的 ofAllowMultiSelect应为true,不然无法一次选择多个文件---------}
procedure TForm1.Button2Click(Sender: TObject);
begin
Wavfiles.Items.Clear;
if OpenDlg.Execute then
begin
Wavfiles.Items.AddStrings(OpenDlg.Files);
Total := WavFiles.Count;
label1.Caption := '共计'+InttoStr(Total)+
'个wav文件。';
end;
end;
先得到文本框的handle,然后用getwindowtext()
使用该消息涉及一个TcopyDataStruct结构类型的指针。该结构中有三个成员:dwData 是一个32位的附加参数cbData 表示要传递的数据区的大小lpData 表示要传递的数据区的指针下面举个例子。该例子由两个程序构成,分别为SendData和GetData。SendData程序向GetData程序发送消息,并传递edit1中的字符串;GetData在收到消息后,把SendData发送的字符串接受下来,并显示在相应的edit1中。SendData程序:
……varForm1: TForm1;implementation{$R *.DFM}procedure TForm1.Button1Click(Sender: TObject);vards: TCopyDataStruct;hd: THandle;beginds.cbData := Length (Edit1.Text) + 1;GetMem (ds.lpData, ds.cbData ); //为传递的数据区分配内存StrCopy (ds.lpData, PChar (Edit1.Text));Hd := FindWindow (nil, 'Form2'); // 获得接受窗口的句柄if Hd <> 0 thenSendMessage (Hd, WM_COPYDATA, Handle,Cardinal(@ds)) // 发送WM_COPYDATA消息elseShowMessage ('目标窗口没找到!');FreeMem (ds.lpData); //释放资源end;GetData程序:
TForm2 = class(TForm)Edit1: TEdit;private{ Private declarations }publicprocedure Mymessage(var t:TWmCopyData);message WM_COPYDATA;{ Public declarations }end;varForm2: TForm2;implementationprocedure TForm2.Mymessage(var t:TWmCopyData);beginEdit1.text:=StrPas(t.CopyDataStruct^.lpData);//接受数据并显示。end;使用这种方法是WIN32应用程序进行交互的最简单的方法。使用全局原子
Win32系统中,为了实现信息共享,系统维护了一张全局原子表。每个原子中存放了一些共享数据。关于对原子的操作,有一组专门的API函数:GlobalAddAtom 在表中增加全局原子GlobalDeleteAtom 在表中删除全局原子GlobalFindAtom 在表中搜索全局原子GlobalGetAtomName 从表中获取全局原子笔者用这种方法实现了避免程序二次启动,但把第二次启动所带的参数传到第一个实例中以进行相应的处理的程序。基本处理如下:在工程文件中:program Pvdde;usesForms,shellapi,Windows,dialogs,dde in 'dde.pas' {Form1};{$R *.RES}beginif GlobalFindAtom(PChar('PDDE_IS_RUNNING')) = 0 then//避免二次启动beginK:=GlobalAddAtom(PChar('PDDE_IS_RUNNING'));Application.Initialize;Application.CreateForm(TForm1, Form1);Application.Run;endelsebegin//传递二次启动时的参数到第一个实例H := FindWindow(PChar('TForm1'), PChar('资料保密 严禁外传'));if ParamCount > 0 thenbeginL := GlobalAddAtom(PChar(ParamStr(1)));if H<>0 thenSendMessage(H, WM_MYMESSAGE, 0, L); { 传递原子句柄 }GlobalDeleteAtom(L); { 使用后释放 }end;Application.Terminate;end;end.在相应的窗口单元dde.pas增加对自定义消息WM_MYMESSAGE的处理:procedure TForm1.MyMessage(var T:TMessage); {对 WM_MYMESSAGE消息进行处理 }varP:Array [0..255] of char;beginGlobalGetAtomName(T.LParam, P,255); { 接受数据到p数组中 }end;使用存储映象文件
这种方法相对较复杂一些。当Win95与Winows Nt向内存中装载文件时,使用了特殊的全局内存区。在该区域内,应用程序的虚拟内存地址和文件中的相应位置一一对应。由于所有进程共享了一个用于存储映象文件的全局内存区域,因而当两个进程装载相同模块(应用程序或DLL文件)时,它们实际可以在内存中共享其执行代码。笔者通过调用一个带有特殊参数的CreateFileMapping函数,来间接达到程序间共享内存的目的。下面简要解释一下该函数。HANDLE CreateFileMapping(HANDLE hFile, //文件句柄 LPSECURITY_ATTRIBUTES lpFileMappingAttributes, // 可选安全属性DWORD flProtect, // 映象文件保护方式 DWORD dwMaximumSizeHigh, // 映象文件区域的底值 DWORD dwMaximumSizeLow, // 映象文件区域的顶值 LPCTSTR lpName // 映象文件的名字); 如果hFile是0xFFFFFFFF,在调用程序中必须指定dwMaximumSizeHigh 和dwMaximumSizeLow参数的值以确定映象文件的大小。通过这样的参数指定,该函数就创建了一个由操作系统页文件支持的特殊逻辑映象文件,而不是由实际操作系统的文件支持的逻辑映象文件。这个逻辑映象文件可以通过复制、继承或者按名字来达到共享。至于其它参数的详细说明,请参看在线帮助。在建立了映象文件之后,我们可以通过调用另外一个API函数MapViewOfFile来访问它的内存,该函数会返回一个指向共享内存块的特定指针。LPVOID MapViewOfFile(HANDLE hFileMappingObject, // 映象文件句柄 DWORD dwDesiredAccess, // 访问方式 DWORD dwFileOffsetHigh, // 映象文件区域的底值 DWORD dwFileOffsetLow, // 映象文件区域的顶值DWORD dwNumberOfBytesToMap // 映射字节数);如果 dwNumberOfBytesToMap 是0,映射整个文件。以下举例说明:privatehMapFile: THandle;MapFilePointer: Pointer;public{ Public declarations }end;varForm1: TForm1;implementation{$R *.DFM}procedure TForm1.FormCreate(Sender: TObject);beginhMapFile := CreateFileMapping ($FFFFFFFF, // 特殊内存映射句柄nil, page_ReadWrite, 0,10000, 'DdhDemoMappedFile'); // 文件名if hMapFile <> 0 thenMapFilePointer := MapViewOfFile (hMapFile, // 上面映象文件的句柄File_Map_All_Access, 0, 0, 0) // 访问整个映象文件elseShowMessage ('hMapFile = 0');if MapFilePointer = nil thenShowMessage ('MapFilePointer = nil');end; procedure TForm1.BtnWriteClick(Sender: TObject);beginStrCopy (PChar (MapFilePointer),PChar (EditWrite.Text));//把内容写入共享内存end; procedure TForm1.BtnReadClick(Sender: TObject);varS: string;beginS := PChar (MapFilePointer);//从共享内存读出内容EditRead.Text := S;end;用这种方法,不但可以在不同的程序之间共享数据,还可以在同一程序的不同实例间共享数据。为了及时通知其它进程共享数据的变化,可以自定义一条用户消息,通过发消息来实现,这里不再赘述。利用以上三种方法均可以有效地实现数据传递、共享,所有的例子程序均在Delphi 3.0,4.0下调试通过。