要求:
VC编写一带窗体DLL
Delphi中有一个panel
在delphi程序中可以调用VC编写的DLL.并调用其窗体,使其窗体出现在Delphi程序中的Panel里,即VC DLL窗体的Parent为delphi中的panel句柄.
谁能给出符合要求的例子,高分相送,另开贴送分!

解决方案 »

  1.   

    传delphi中的panel的handle过去,把VC的窗体的Parent指向该handle,这只是个思路,感觉不一定行.
      

  2.   

    DLL中的窗体必须动态创建。
    其实VC创建一个窗体作为一个空间的子项比Delphi还要简单方便些。
    别忘了,VC没有PageContorl只有TabControl,我们做的时候,不就是把一个对话框作为子空间Create 到该TabControl上的吗,而且只需要parent的HWnd
      

  3.   


    大家在软件开发时经常会遇到这样的情况,在不同的开发环境中为实现一些功能相同的过程,由于开发所使用的设计语言不同,因而不得不编写许多类似的代码,甚至有时要在同一个开发环境不同项目中重写代码,这就造成了很大的资源浪费。动态链接库能较好的解决这个问题,重复利用代码将大大提高了开发效率。一般,用户在应用程序中基于如下要求创建和使用DLL:1. 在不同的可执行文件之间共享的程序;2. 在设计应用程序时,将其拆分成各个相互独立功能部件,为以后这些功能部件各自升级提供方便的途径。动态链接库将共享程序或功能部件做成库中的函数,形成DLL文件,其它应用程序通过使用DLL调用这些函数。在这里将对Delphi和VC中创建和使用动态链接库的方法做一介绍。Delphi和VC定义的动态链接库均可在两者的开发环境中使用。一、 用Delphi创建DLLDelphi的DLL创建并不复杂,下面向大家介绍Delphi的DLL创建方法。(1)首先创建一个新的DLL项目(NewProject)project1,文件头部为:library Project1; (2)USES语句后面加入ExPorts语句,指明调用DLL的函数名,形式为:exports  checkpwd name 'checkpwd'; (3)在DLL的Pas文件中Type......End后加入该DLL的函数或过程的声明,形式如下:FunctionName(argment):Boolean;export; 该函数也可以存在于另一个pas文件中(如Unit1.pas),此时只需在项目文件中加入:uses  Unit1 in 'Unit1.pas' {Form1}; 值得注意的是,该函数或过程应加入窗体的Create和Free(产生和释放)方法。(4)对项目进行编译即形成DLL文件,可被其它项目调用。二、Delphi中DLL的调用调用DLL有两种方法,一种是在应用程序装载时调用,另一种是在应用程序运行时调用。(1) 装载时调用DLL在调用DLL的Pas文件中,对DLL函数进行外部声明,声明应位于Implementation后,形式如下:Implementation  Function functionname(argment):Boolean;far;External 'DllName'; 其中External关键字后面的引号内是DLL的文件名,该文件一般应放在系统的system目录下,或与调用它的项目同一目录。声明以后即可在Pas文件任何地方引用DLL函数。装载时调用DLL的优点是速度较快,程序间也可共享代码。(2) 运行时调用DLLDLL的另一种调用方法是在运行时调用。这种方法要调用到Windows的API函数LoadLibrary,GetProcAddress,FreeLibrary等。此方法主要用于调用其它语言,特别是C++编译的DLL。假定你欲调用的DLL中包括一个函数:Function checkpwd(pwd:string):boolean;export; 那么,首先在欲调用DLL的程序Type类型声明处加入一句:Type  Tcheckpwd= function(pwd:string):boolean; 此句的作用如同C++中声明的函数指针。然后定义如下变量∶Var  aptr:TFarproc;  lhnd:THandle;  flag:boolean; 其中Aptr,lhnd两变量声明必须有,flag是DLL函数返回值,视情况而定。在调用DLL处加入如下语句进行DLL装载:lhnd:=Loadlibrary('路径:DLL文件名');{如lhnd:=Loadlibrary('c:\project1.dll');  aptr:=GetprocAddress(lhnd,'checkpwd'); 下面可直接调用DLL了:flag:=Tcheckpwd(aptr)( 'pwd');{根据函数填相应的变量参数} 调用完以后,用FreeLibrary释放DLL占用的内存:FreeLibrary(lhnd);三、用VC创建DLL在VC中创建DLL,与Delphi中的创建过程相似,步骤如下:(1)新建一个DLL项目。MFC提供两种类型的动态链接库:常规型DLL、扩展型DLL。其中,常规型DLL适合于非MFC开发环境下采用支持DLL调用的程序设计语言开发的应用程序,扩展型DLL只能被MFC程序使用。(2)创建该DLL中的过程或函数,只需在程序中加入下列语句:extern "C" _declspec(dllexport)   int yanzheng(CString input,char* zcm)  {  AFX_MANAGE_STATE(AfxGetStaticModuleState());  file://具体实现过程  } 该函数的功能是验证注册码是否合法,其中yanzheng为函数名,int为函数返回值类型,()内为函数参数。编译通过后即可使用。
      

  4.   

    四、 VC中DLL的调用在VC中调用动态链接库时,类似于Delphi中运行时调用DLL的方法。也要调用到Windows的API函数LoadLibrary,GetProcAddress等。此方法对于调用其它语言和VC编译的DLL均适用。假定DLL中包括一个函数:int yanzheng(CString input,char* zcm) 首先在欲调用DLL函数的cpp文件前部先声明函数指针,定义函数类型:typedef int (* _YANZHENG)(CString,char* zcm); 然后定义如下变量∶HINSTANCE hLibrary;  _YANZHENG yanzheng; 在调用DLL处加入如下语句进行DLL装载: hLibrary=LoadLibrary("zcdll.dll");  yanzheng=(_YANZHENG)GetProcAddress(hLibrary,"yanzheng");  shuchu= (*yanzheng)(shuru,zcm);  FreeLibrary(hLibrary); 五、 几点提示(1)如果用Delphi创建DLL时用到其它的form,则在DLL的输出函数中应包括form的create(创建)和free(释放),而且在显示该窗口时只能用showmodal过程,不能用show过程,在后面的例子中能详细看到。(2)如果Delphi创建的DLL中的函数或过程,用string类型作为参数输入或返回string类型,当用VC或其它程序调用时,经常会出错,反之亦然。为了解决这种情况,使不同程序之间在使用字符串类型时,接口更安全,建议使用pchar类型,而不是string类型。而且要在程序中加入内存管理,使用系统提供的sharemem单元。下面是一个实现将星期标识由数字转换成英文的例子:uses  sharemem;  exports  makeitaday;  var   mydate:pchar;  function makeitaday(S:integer):pchar;stdcall;export;  implementation  function makeitaday(S:integer):pchar;stdcall;export;  var  thedate:array[0..20] of char;  begin  GetMem(mydate, 200);  if s=1 then thedate:='Sunday ';  file://……….  strpcopy(mydate,thedate);  makeitaday:=mydate;  end; 六、实例因为用Delphi创建和调用DLL,过程与用VC创建和调用DLL相似,只是前者代码要比在VC环境中稍微复杂一些,因此在文章的最后给出一个完整的用Delphi创建和调用DLL的例子。该DLL主要用来检查输入的口令是否正确,窗体含有一个Edit编辑框,一个按钮Button,在编辑框内输入口令,比较编辑框的值和输入参数返回真假值。//文件名为checkpassword.dpr;编译此文件生成checkpassword.dll   library checkpassword;  uses  SysUtils, Classes, Unit1 in 'Unit1.pas' {Form1};  exports  checkpwd name 'checkpwd';//声明DLL函数  {$R *.RES}  begin  end.file://文件名为unit1.pas   unit Unit1;  interface  uses  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;  type  TForm1 = class(TForm)  password: TEdit;  Button1: TButton;  procedure Button1Click(Sender: TObject);  private  { Private declarations }  public  { Public declarations }  end;  var  Form1: TForm1;  flag:boolean;//返回输入密码是否正确  rightpwd:string;//记录输入参数(正确的密码)  function checkpwd(pwd:string):boolean;export;//声明DLL函数  implementation  {$R *.DFM}  procedure TForm1.Button1Click(Sender: TObject);  begin  if password.text=rightpwd then  flag:=true;  form1.close;  end;function checkpwd(pwd:string):boolean;export;  begin  flag:=false;  rightpwd:=pwd;//读入正确的密码值  form1:=Tform1.create(Application);//创建密码验证窗口  form1.ShowModal;//显示窗口  checkpwd:=flag;  form1.free;//释放资源  end;  end.file://主程序main.pas,调用DLL  unit main;  interface  uses  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;  type  TForm1 = class(TForm)  jieguo: TEdit;  Button1: TButton;  procedure Button1Click(Sender: TObject);  private  { Private declarations }   public  { Public declarations }  end;  var  Form1: TForm1;  implementation  function checkpwd(pwd:string):boolean;external 'project1.dll' ;//函数说明  {$R *.DFM}  procedure TForm1.Button1Click(Sender: TObject);  begin  if checkpwd('congrong') then//调用函数  jieguo.text:='true'  else  jieguo.text:='false';  end;  end.  
      

  5.   

    谢谢,,但是用不上!VC,Delphi中创建调用Dll窗体,我记得可能都作过!现在唯一难的就是像我题目所说的那样,请大家继续帮忙!
      

  6.   

    呵呵,确实用不上,你可以用ActiveForm
      

  7.   

    1,使用ACTIVEX技术。2,仅仅是传一个窗口句柄设为父窗口就行,但VCL自已在WINDOWS基础上扩展了一系列机制。
    这样VC编写的嵌入窗口要想达到同DELPHI窗体协调一体有大量工作要做。。
      

  8.   

    我正在做在delphi的一个窗口中显示vc做的窗口,不过我想用api函数实现与delphi程序的接口,也就是在vc程序中得到delphi程序的窗口句柄进行操作,关注你的问题.
      

  9.   

    TO halfdream(哈欠)你的第二个方法还有哪些工作要作?
      

  10.   

    感觉不是简单的传递个handle就可以了的,现在还没有想明白。 sunsmell(海鸟) 说说你是怎么做的?
      

  11.   

    举个例子:
    int draw(HWND hwnd)
    {
    HDC hdc;
    CRect rect;
    CDC *pdc=new CDC( );
    hdc=GetDC(hwnd);
    pdc->Attach(hdc);
    GetClientRect(hwnd,&rect);
    pdc->MoveTo(rect.left,rect.top);
    pdc->LineTo(rect.right,rect.bottom);
    ReleaseDC(hwnd,hdc);
    delete pdc; return 0;
    }
    delphi中的panel的hwnd传给draw函数,此函数在panel上画一条对角线对于在Panel中显示子窗口,我建议你在vc中定义一个CWND派生的类,然后用函数将其与delphi接口封装起来,就可以了
      

  12.   

    我以前是这样做的!_declspec(dllexport) WINAPI Test(cwnd *i)
    {
    AFX_MANAGE_STATE(AfxGetStaticModuleState());
    CTest CDlg;
    CDlg.Create(IDD_DIALOG1,i);            //这里出错;
    CDlg.ShowWindow(TRUE);
    }如果不用Create,而用ShowModal的话,是完全可行的!
    但是加上Create就会出错..现在主要解决的是这部分.而且后面还有一部分分SetParent这部分没做到,不知道会不会出错!
      

  13.   

    这个问题比较简单,子类化VC中的窗口,处理它的WM_Paint事件,然后修改设备句柄为你需要的句柄即可。
      

  14.   

    我试验了一下,建议用API:SetParent
      

  15.   

    TO: ZQJ
    能不能发个例子来看一下!
      

  16.   

    vc的dll用vs.net2003做的,新建一个dll工程testdll
    下面是testdll.cpp 文件
    // testdll.cpp : 定义 DLL 应用程序的入口点。
    //#include "stdafx.h"
    #include "resource.h"
    #include "testdll.h"HINSTANCE hInst; // 当前实例
    LRESULT CALLBACK CALLPROC(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);BOOL APIENTRY DllMain( HANDLE hModule, 
                           DWORD  ul_reason_for_call, 
                           LPVOID lpReserved
     )
    {
       switch (ul_reason_for_call)
        {
            case DLL_PROCESS_ATTACH:
    hInst = (HINSTANCE)hModule;
    break;
            case DLL_THREAD_ATTACH:
    break;
            case DLL_THREAD_DETACH:
    break;
            case DLL_PROCESS_DETACH:
    break;
    default:
    break;
        }
    return TRUE;
    } __declspec(dllexport) BOOL CallDialog(HWND hWnd)
    {
    //RECT rc;
    HWND hwndCall=NULL;
    hwndCall = CreateDialog(hInst,MAKEINTRESOURCE(IDD_DLGCALL),NULL,(DLGPROC)CALLPROC); 
    //GetWindowRect(hWnd, &rc);  //SetWindowPos(hwndCall,HWND_TOPMOST,rc.right-100,rc.top+50,90,157,NULL);
    SetParent(hwndCall,hWnd);
    //SetWindowPos(hwndCall,NULL,rc.right-420,rc.top+200,152,260,NULL);
    ShowWindow(hwndCall, SW_SHOW); 
    return(true);
    }
    // “调用”框的消息处理程序。
    LRESULT CALLBACK CALLPROC(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
    {
    switch (message)
    {
    case WM_INITDIALOG:
    return TRUE; case WM_COMMAND:
    if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) 
    {
    EndDialog(hDlg, LOWORD(wParam));
    return TRUE;
    }
    break;
    }
    return FALSE;
    }
      

  17.   

    下面是testdll.h 文件#ifdef __cplusplus
    extern "C" {
    #endif
    __declspec(dllexport) BOOL CallDialog(HWND hWnd);#ifdef __cplusplus
    }
    #endif
    下面是stdafx.h
    // stdafx.h : 标准系统包含文件的包含文件,
    // 或是常用但不常更改的项目特定的包含文件
    //#pragma once
    #define WIN32_LEAN_AND_MEAN // 从 Windows 头中排除极少使用的资料
    // Windows 头文件:
    #include <windows.h>
    // Windows 头文件:
    #include <string.h>
    #include <stdio.h>
    #include <stdlib.h>// TODO: 在此处引用程序要求的附加头文件
    下面是stdafx.cpp 
    // stdafx.cpp : 只包括标准包含文件的源文件
    // testdll.pch 将成为预编译头
    // stdafx.obj 将包含预编译类型信息#include "stdafx.h"// TODO: 在 STDAFX.H 中
    //引用任何所需的附加头文件,而不是在此文件中引用下面是testdll.rc
    // Microsoft Visual C++ generated resource script.
    //
    #include "resource.h"#define APSTUDIO_READONLY_SYMBOLS
    /////////////////////////////////////////////////////////////////////////////
    //
    // Generated from the TEXTINCLUDE 2 resource.
    //
    #include "afxres.h"/////////////////////////////////////////////////////////////////////////////
    #undef APSTUDIO_READONLY_SYMBOLS/////////////////////////////////////////////////////////////////////////////
    // 中文(中华人民共和国) resources#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
    #ifdef _WIN32
    LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
    #pragma code_page(936)
    #endif //_WIN32#ifdef APSTUDIO_INVOKED
    /////////////////////////////////////////////////////////////////////////////
    //
    // TEXTINCLUDE
    //1 TEXTINCLUDE 
    BEGIN
        "resource.h\0"
    END2 TEXTINCLUDE 
    BEGIN
        "#include ""afxres.h""\r\n"
        "\0"
    END3 TEXTINCLUDE 
    BEGIN
        "\r\n"
        "\0"
    END#endif    // APSTUDIO_INVOKED
    /////////////////////////////////////////////////////////////////////////////
    //
    // Dialog
    //IDD_DLGCALL DIALOGEX 0, 0, 186, 94
    STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_SYSMENU | WS_THICKFRAME
    FONT 8, "MS Shell Dlg", 400, 0, 0x1
    BEGIN
        DEFPUSHBUTTON   "确定",IDOK,129,7,50,14
        PUSHBUTTON      "取消",IDCANCEL,129,26,50,14
    END
    /////////////////////////////////////////////////////////////////////////////
    //
    // DESIGNINFO
    //#ifdef APSTUDIO_INVOKED
    GUIDELINES DESIGNINFO 
    BEGIN
        IDD_DLGCALL, DIALOG
        BEGIN
            LEFTMARGIN, 7
            RIGHTMARGIN, 179
            TOPMARGIN, 7
            BOTTOMMARGIN, 87
        END
    END
    #endif    // APSTUDIO_INVOKED#endif    // 中文(中华人民共和国) resources
    /////////////////////////////////////////////////////////////////////////////#ifndef APSTUDIO_INVOKED
    /////////////////////////////////////////////////////////////////////////////
    //
    // Generated from the TEXTINCLUDE 3 resource.
    //
    /////////////////////////////////////////////////////////////////////////////
    #endif    // not APSTUDIO_INVOKED下面是resource.h
    //{{NO_DEPENDENCIES}}
    // Microsoft Visual C++ generated include file.
    // Used by testdll.rc
    //
    #define IDD_DIALOG1                     102
    #define IDD_DLGCALL                     102// Next default values for new objects
    // 
    #ifdef APSTUDIO_INVOKED
    #ifndef APSTUDIO_READONLY_SYMBOLS
    #define _APS_NEXT_RESOURCE_VALUE        103
    #define _APS_NEXT_COMMAND_VALUE         40001
    #define _APS_NEXT_CONTROL_VALUE         1001
    #define _APS_NEXT_SYMED_VALUE           101
    #endif
    #endif
      

  18.   

    win32的API SetParent解决问题,
      HWND SetParent(
        HWND hWndChild, // handle of window whose parent is changing //VC中的窗口句柄
        HWND hWndNewParent  // handle of new parent window   //Delphi中的Panel的句柄
       );
    就两个参数,不用解释了吧。
      这么个问题,楼上的长篇大论,干啥呢,I 服了 u
      

  19.   

    既然已经是长篇大论,就再加点,下面是调用例子
    我这里只有cb6
    先产生一个testdll.h供dll调用
    extern "C"
    {__int16  __stdcall CallDialog(HANDLE hWnd);}然后new一个application
    在form上放一个panel,在放一个button,在button的click放
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
        bool aa;
        aa=CallDialog(Panel1->Handle);
    }如果要改变显示的位置,请改变我给你的dll中setpos那句就好了。
      

  20.   

    TO: humingfei(Edgar.Hu)你的信我看过!你的例子我也试过,,你给的例子可用,,但是我用delphi编一个exe调用你用vs.net写的DLL时会出现一个错误,,而用VC6写的DLL根本就调用不出窗口.TO: ZQJ(Afflatus)谢谢你的关注,,但是理论与实际往往是不相符的,你说的有道理,但是请先实现出来好吗?我当时也想的很简单但是很久都没有实现出来!
      

  21.   

    我写了一个例子,已经发给你了,没有任何问题,代码如下delphi7:unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, ExtCtrls, StdCtrls;type
      TForm1 = class(TForm)
        Button1: TButton;
        Panel1: TPanel;
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
    hd:THandle ;
    cd:TFarProc;
      Form1: TForm1;implementation{$R *.dfm}
    //procedure cd(H:THandle);
    //cdecl;
    //external 'testdll.dll';procedure TForm1.Button1Click(Sender: TObject);
    type
    TIntFunc=function(h:THandle):integer; cdecl;
    var
    tf:TIntFunc;
    aa:integer;
    begin  hd:=LoadLibrary('c:\test\testdll.dll');
      cd:=GetProcAddress(hd,'CallDialog');
      tf:=TIntFunc(cd);
      aa:=tf(Panel1.Handle);
    end;end.
      

  22.   

    上面这个例子写的比较次,大家千万不要批我,我也是马上要下班回家,借用别人的计算机上的delphi7写的,而且我有两年没有摸过delphi了。但可以确保没有任何问题。
    注意上面这个例子中的dll档写死了dll档的路径!
      

  23.   

    humingfei(Edgar.Hu) 
    牛人!
      

  24.   

    嗯,按humingfei(Edgar.Hu)所说,基本已解决!!送分贴子地址:http://community.csdn.net/Expert/topic/3570/3570892.xml?temp=.7373163
    请humingfei(Edgar.Hu) 接分!
      

  25.   

    兄弟,我找了几台计算机,我们公司已经没有人用vc6了,如果你用lib的方式进行编译的话,用vc6生成的dll档要用implib产生lib才可以。