如何在窗体中嵌入一个被调用的exe文件?小妹急求~谢谢!

时间:2023-02-04 23:33:11
    是这样的,我想在form的一个panel里显示一个外部的exe,我目前只能用ShellExecute方法调用外部exe文件,是在一个新窗口打开的,我想在我自己程序的窗体上显示打开,而不是在新的窗口打开,有什么办法可以解决么?先谢过了~


    其中我找到一段代码 是用c#写的,我不会c#,他写的很复杂,小妹实在看不太懂,不知道这个方法在BCB中怎么用,贴出来给大家看下
http://www.cnblogs.com/jdmei520/archive/2009/06/05/1497124.html

12 个解决方案

#1


如何在窗体中嵌入一个被调用的exe文件?小妹急求~谢谢!

#2


procedure TForm1.Button1Click(Sender: TObject);
var
    H1,H2: Hwnd;
begin
    // 先執行要放入專案的外部EXE檔案(用隱藏方式來執行)
    WinExec('C:\Program Files\TOOLS\MYIE\MyIE.exe',SW_HIDE);
    // 再找到該外部EXE檔案
    H1 := FindWindow(nil,PChar('MyIE'));
    // 假設找到執行之程式後要放在 Panel1
    H2 := Panel1.Handle;
    // 將外部程式放在 Panel1
    Windows.SetParent(H1,H2);
    // 設定外部程式顯示的位置及大小
    // MoveWindow(hWnd,X,Y,W,H,B) : RETURN BOOL
    //        hWnd: HWND
    //        X:Integer; {horizontal}
    //        Y:Integer; {vertical}
    //        W:Integer; {the new window width}
    //        H:Integer; {the new window height}
    //        B:BOOL;    {the repaint flag}
    MoveWindow(H1,0,0,Panel1.Width,Panel1.Height,True);
    //
    Windows.ShowWindow(H1,SW_ShowNormal);
end;

#3



  HWND hwnd,chwnd;
  hwnd=this->Panel1->Handle;
  ShellExecute(hwnd, "open", "calc.exe" ,"", "C:\WINDOWS\system32", SW_HIDE );
  Sleep(100);
  chwnd=::FindWindow("SciCalc","计算器");
  if(chwnd!=NULL)
  {
     ::SetParent(chwnd,hwnd);
     ::MoveWindow(chwnd,0,0,Panel1->Width,Panel1->Height,true);
  }

bcb6下测试通过。

#4


顶,在BCB版块,见到MM还真是难得啊。

#5


十分感谢大家!!!!我试过了,好像还有个问题,就是FindWindow,我不知道那个lpClassName参数,怎么办?有什么方法么?谢谢!!

#6


可以用Visual studio里的spy++来监听窗口的各种信息。
做法是:
1、打开被查看窗口
2、运行spy++
3、点FindWindow
4、拖动FindWindow中间的图标到你的窗口上
5、spy++里就显示你要的结果了

#7


感谢各位大虾!!!!小妹试过了,好像又有个问题!我用spy++测试弹出的窗口,发现 每次窗口的句柄与类名都是不同的!Spy++显示如下
窗口句柄 60F4C 
窗口类名 Afx:00400000:0:00010011:0110006B:003B0FC9
由于这个类名每次变化不同,所以无法作为lpClassName参数传递,但是窗口的标题文本不发生变化,所以我尝试将FindWindow的第一个参数赋NULL,但是FindWindow的返回值一直为空指针不知为何?
有什么解决办法?
谢谢!!

#8


代码贴出来看看

#9


窗口句柄每次打开都会变化是正常现象,类名一般不会变哦!
也有可能你输入的窗口标题不对,要全字符匹配的。差一个字都不行,当然你可以EnumWindows来枚举窗口,这样稍微麻烦一点,但可以做到不全字符匹配,如下是实现代码:
BOOL CALLBACK EnumWindowsProc(HWND hwnd,LPARAM lParam)
{
    char    str[100];
    GetWindowText(hwnd, str, 100);
    if(strstr(str, "C++"))
    {
        ShowMessage(str);
        return FALSE;
    }
    return TRUE;
}

void __fastcall TForm1::Button1Click(TObject *Sender)
{
    WNDENUMPROC lp = (WNDENUMPROC)EnumWindowsProc;

    EnumWindows(lp, NULL);
}

#10


再次谢谢大家,今天调了下程序,发现了问题的原因,使用hnzlk朋友的如下代码并进行了修改:
hwnd=this->Panel1->Handle;
ShellExecute(hwnd, "open", "zuhe.exe" ,"", "E:\\workdir\\Cbuilder\\test3", SW_HIDE);
Sleep(10000);
chwnd=::FindWindow(NULL,"3DVIA Composer Player - zuhe.smg");
if(chwnd!=NULL)
{
   ::SetParent(chwnd,hwnd);
   ::MoveWindow(chwnd,0,0,Panel1->Width,Panel1->Height,true);
}
第一次没有成功,是因为Sleep的时间不够长 = =!
因为我的这个exe文件很大,是用第3方软件生成的,打开至少需要5秒钟,再大一点的需要近10秒,只有打开完全后,才能找到窗口。

现在Sleep10秒,FindWindow函数可以找到窗口了,但是exe打开的过程中是全屏显示,而且打开的时间不定。。就让人觉得程序分了家了一样,能不能让exe打开的时候,就处在panel的窗口之中呢?

初步设想让exe在后台打开,不显示出来,软件界面可以等待稍微长一些,但是ShellExecute函数的参数SW_HIDE,SW_MINIMIZE 等对这个exe不起作用,可能因为这个exe包含了第三方软件的程序。。不知道有什么好的解决办法没有?

恳请大虾帮忙!!谢谢啦!!

#11


谢谢大家!

#12



http://www.cnblogs.com/jdmei520/archive/2009/06/05/1497124.html

这个的代码很好用,我刚刚弄过了,谢谢了!

#1


如何在窗体中嵌入一个被调用的exe文件?小妹急求~谢谢!

#2


procedure TForm1.Button1Click(Sender: TObject);
var
    H1,H2: Hwnd;
begin
    // 先執行要放入專案的外部EXE檔案(用隱藏方式來執行)
    WinExec('C:\Program Files\TOOLS\MYIE\MyIE.exe',SW_HIDE);
    // 再找到該外部EXE檔案
    H1 := FindWindow(nil,PChar('MyIE'));
    // 假設找到執行之程式後要放在 Panel1
    H2 := Panel1.Handle;
    // 將外部程式放在 Panel1
    Windows.SetParent(H1,H2);
    // 設定外部程式顯示的位置及大小
    // MoveWindow(hWnd,X,Y,W,H,B) : RETURN BOOL
    //        hWnd: HWND
    //        X:Integer; {horizontal}
    //        Y:Integer; {vertical}
    //        W:Integer; {the new window width}
    //        H:Integer; {the new window height}
    //        B:BOOL;    {the repaint flag}
    MoveWindow(H1,0,0,Panel1.Width,Panel1.Height,True);
    //
    Windows.ShowWindow(H1,SW_ShowNormal);
end;

#3



  HWND hwnd,chwnd;
  hwnd=this->Panel1->Handle;
  ShellExecute(hwnd, "open", "calc.exe" ,"", "C:\WINDOWS\system32", SW_HIDE );
  Sleep(100);
  chwnd=::FindWindow("SciCalc","计算器");
  if(chwnd!=NULL)
  {
     ::SetParent(chwnd,hwnd);
     ::MoveWindow(chwnd,0,0,Panel1->Width,Panel1->Height,true);
  }

bcb6下测试通过。

#4


顶,在BCB版块,见到MM还真是难得啊。

#5


十分感谢大家!!!!我试过了,好像还有个问题,就是FindWindow,我不知道那个lpClassName参数,怎么办?有什么方法么?谢谢!!

#6


可以用Visual studio里的spy++来监听窗口的各种信息。
做法是:
1、打开被查看窗口
2、运行spy++
3、点FindWindow
4、拖动FindWindow中间的图标到你的窗口上
5、spy++里就显示你要的结果了

#7


感谢各位大虾!!!!小妹试过了,好像又有个问题!我用spy++测试弹出的窗口,发现 每次窗口的句柄与类名都是不同的!Spy++显示如下
窗口句柄 60F4C 
窗口类名 Afx:00400000:0:00010011:0110006B:003B0FC9
由于这个类名每次变化不同,所以无法作为lpClassName参数传递,但是窗口的标题文本不发生变化,所以我尝试将FindWindow的第一个参数赋NULL,但是FindWindow的返回值一直为空指针不知为何?
有什么解决办法?
谢谢!!

#8


代码贴出来看看

#9


窗口句柄每次打开都会变化是正常现象,类名一般不会变哦!
也有可能你输入的窗口标题不对,要全字符匹配的。差一个字都不行,当然你可以EnumWindows来枚举窗口,这样稍微麻烦一点,但可以做到不全字符匹配,如下是实现代码:
BOOL CALLBACK EnumWindowsProc(HWND hwnd,LPARAM lParam)
{
    char    str[100];
    GetWindowText(hwnd, str, 100);
    if(strstr(str, "C++"))
    {
        ShowMessage(str);
        return FALSE;
    }
    return TRUE;
}

void __fastcall TForm1::Button1Click(TObject *Sender)
{
    WNDENUMPROC lp = (WNDENUMPROC)EnumWindowsProc;

    EnumWindows(lp, NULL);
}

#10


再次谢谢大家,今天调了下程序,发现了问题的原因,使用hnzlk朋友的如下代码并进行了修改:
hwnd=this->Panel1->Handle;
ShellExecute(hwnd, "open", "zuhe.exe" ,"", "E:\\workdir\\Cbuilder\\test3", SW_HIDE);
Sleep(10000);
chwnd=::FindWindow(NULL,"3DVIA Composer Player - zuhe.smg");
if(chwnd!=NULL)
{
   ::SetParent(chwnd,hwnd);
   ::MoveWindow(chwnd,0,0,Panel1->Width,Panel1->Height,true);
}
第一次没有成功,是因为Sleep的时间不够长 = =!
因为我的这个exe文件很大,是用第3方软件生成的,打开至少需要5秒钟,再大一点的需要近10秒,只有打开完全后,才能找到窗口。

现在Sleep10秒,FindWindow函数可以找到窗口了,但是exe打开的过程中是全屏显示,而且打开的时间不定。。就让人觉得程序分了家了一样,能不能让exe打开的时候,就处在panel的窗口之中呢?

初步设想让exe在后台打开,不显示出来,软件界面可以等待稍微长一些,但是ShellExecute函数的参数SW_HIDE,SW_MINIMIZE 等对这个exe不起作用,可能因为这个exe包含了第三方软件的程序。。不知道有什么好的解决办法没有?

恳请大虾帮忙!!谢谢啦!!

#11


谢谢大家!

#12



http://www.cnblogs.com/jdmei520/archive/2009/06/05/1497124.html

这个的代码很好用,我刚刚弄过了,谢谢了!