function EnumWindowsProc(Wnd: HWnd;
  LPARAM: lParam): boolean; stdcall;
var
  lb_return : longbool;
  lpc_text : array[0..254] of char;
begin
  //getwindowtextA(wnd,lpc_text,254);
  showwindow(wnd,sw_minimize);
  result := true;
end;procedure Func_ShowDesk();
var
li_return : boolean;
i : integer;
begin
   li_return := EnumWindows(@EnumWindowsProc,0);
end;

解决方案 »

  1.   

    (*
    BOOL CALLBACK EnumWindowsProc(    HWND hwnd, // handle to parent window
        LPARAM lParam  // application-defined value
       );BOOL EnumWindows(    WNDENUMPROC lpEnumFunc, // pointer to callback function
        LPARAM lParam  // application-defined value
       );
    *)
    type
      TEnumWindowsProc = function(hwnd: HWND; lParam: LParam): BOOL; stdcall;function EnumWindowsProc(hwnd: HWND; lParam: LParam): BOOL; stdcall;
    begin
      Result := False;
      ShowMessage(IntToStr(hwnd));
      if MessageDlg('Continue?', mtInformation, [mbYes, mbNo], 0) = mrNo then Exit;
      Result := True;
    end; { EnumWindowsProc }var
      vEnumWindowsProc: TEnumWindowsProc = EnumWindowsProc;procedure TFormSocket.Button1Click(Sender: TObject);
    begin
      if not Assigned(vEnumWindowsProc) then Exit; //判断函数指针是否为空
      EnumWindows(@vEnumWindowsProc, 0);
    end;
      

  2.   

    三、Windows 消息驱动工作机理讨论================================     由于我们的工作实在太忙,很久没见了,真是不好意思。上一次所给出的程序看懂了吗?什么?没有!没有关系,学习总得有个过程,我刚刚接触学习Windows 编程的时候也是如此。这一次我们就来结合上一次提供的程序代码来将Windows 的基本工作机理----消息驱动来讲一下。     消息驱动,初听起来好象挺吓人的,这么专业,其实也不是那么回事,很简单的。从字面上理解的话就是使用消息来驱动程序,使用消息来和 Windows系统打交道,发送消息的是 Windows,接收消息的是咱们自己编写的程序。就好象在抗日战争中使用的消息树一样,站在消息树旁边的人相当于 Windows,而其它地方观察消息树变化的人则相当于自己编写的应用程序。当发现鬼子的时候,站在消息树旁边的人就会推倒消息树,而其他观察消息树变化的人一看消息树倒了,就明白有情况发生,就会采取相应的行动。就是说使用消息树来驱动别人的行动。     实现消息树就去找一棵树来推就可以了,那么 Windows 是如何实现这一过程的呢?请把上一次提供的程序代码找出来先,我们按照这个程序来讲解。Are you ready ? Go !     Windows 使用了一个特殊的函数来实现这一过程,这个函数的名称叫做“窗口处理函数”或者叫做“窗口消息处理函数”。在自己编写的程序中一定要有这样一个函数,否则...这还用解释?但是这个函数的定义不是随心所欲定义的,要不怎么说它特殊呢,必须遵照规定好的语法来定义,否则 Windows 可不认。在上次的代码中有这么一行: LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ); 这就是规定好的定义语法,但是函数名字可以修改,函数参数和返回值一定不能改。你不喜欢这个名字可以改,比如可以定义为: LRESULT CALLBACK WndProc2( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam );LRESULT CALLBACK WndProc3( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam );LRESULT CALLBACK WndProc4( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ); 只要不修改参数和返回值就成。其中的参数含义为:HWND hwnd:发送窗口的句柄(句柄其实就是一个数值,一个用来标识窗口的数值,相当于我们身份证号码,来唯一的标识一个窗口)。UINT message:消息代码(Windows 中每一个消息都有唯一的一个代号,使用宏来定义好的)。WPARAM wParam:当前发送消息时所带的参数(有些消息需要附带一些数据,就使用个参数)。LPARAM lParam:同上。 当 Windows 有消息需要通知程序的时候,它就会调用该函数,然后自己的程序就从中检测发送的消息。Windows 中消息的种类是很多的,不可能也没有必要检测所有的消息,我们只需要检测感兴趣的消息即可。检测消息的程序代码其实就是一个条件判断组合,就象示例代码中的那样: switch( message ){       // 响应 WM_CREATE 消息       case WM_CREATE:       // 弹出一个对话框通知收到消息       MessageBox( hwnd, "收到 WM_CREATE 消息 !", "通知", MB_OK );       break;        // 响应 WM_DESTROY 消息       case WM_DESTROY:       // 弹出一个对话框通知收到消息       MessageBox( hwnd, "收到 WM_DESTROY 消息,将要退出程序 !", "通知", MB_OK );       PostQuitMessage( 0 );       break;        // 必须调用该函数(Windows 系统规定)       default : return DefWindowProc( hwnd, message, wParam, lParam );} 上面的 WM_CREATE、WM_DESTROY 宏就是 Windows 已经定义好的的消息宏。     那么聪明的你就会问了,我可以仅检测感兴趣的消息,但是我不感兴趣的消息到那里了呢?仔细观察条件判断组合先。在 default 语句中发现了一个 DefWindowProc() 函数吧,这个函数就是处理你不感兴趣没有进行处理的消息的,这个函数是 Windows 提供的,你不感兴趣的消息就让 Windows 来帮你处理好了。细心的读者又会发现了,在响应 WM_DESTROY 消息的代码中有一个 PostQuitMessage( 0 ) 函数,这个函数是用来干吗的呢?它就是用来告诉 Windows 系统“嗨,Windows,我要退出了,拜拜!”,就是用来干这个的,明白吧。     好了,Windows 基本的工作机理讲完了,这可是最最重要的,其他的附件就很容易摆平了。     第一个附件就是程序的入口,顾名思义,一个程序的执行是需要有入口的,不然 Windows怎么会知道一个程序从那里开始运行呢?这就好比你要去北京动物园看大熊猫,可是不知道门在哪里的话就没有办法进去。什么?你会自己找!抬杠!Windows 又没有腿怎么自己找,如果能自己找到岂不比你都聪明,你得告诉它门在哪里。这个程序的大门入口就是一个函数,就是WinMain() 函数。但是这个函数的定义形式也是规定好的,规定比消息处理函数还要严格,连名字都不能改,是 Windows 已经规定好的。为什么?这还用问,想一下吗,如果动物园门口的招牌天天换,今天是动物园,明天改成“XX商场”,后天改成“XX食城”,大后天改成...你找动物园都找不到,何况 Windows 呼。入口函数的定义是: int WINAPI WinMain( HINSTANCE hInstance,                     HINSTANCE hPrevInstance,                     LPSTR lpCmdLine,                     int nCmdShow );参数含义:HINSTANCE hInstance:应用程序实例句柄(和窗口句柄大同小异,窗口句柄用来唯一标识一个                     窗口,程序实例句柄就是用来唯一标识一个应用程序的,否则内存中同时                     运行那么多的程序,你怎么能让 Windows 分的清呢)。HINSTANCE hPrevInstance:该参数已经废除了,不用使用。LPSTR lpCmdLine:命令行参数。int nCmdShow:窗口显示形式(最大化/最小化等等) 必须必须按照改形式来定义,否则 VC++ 编译器会告诉你“喂,老兄,拜托给个入口好不好”。Windows 首先会调用该函数,你在该函数中再加入自己的代码不就运行自己的程序了。     好了,入口定义好了,但是加入什么代码呢?这还用问,自然是创建一个窗口了,Windows 程序没有窗口怎么行。这第二个附件就是创建窗口。创建一个窗口很容易的,调用 Windows 系统提供的 CreateWindow() 就行了。窗口有很多中样子和风格的,在创建之前需要告诉它,这就需要填充一个结构,这个结构就是 WNDCLASS。看代码先。         WNDCLASS wc;       wc.style         = CS_HREDRAW|CS_VREDRAW; // 窗口风格(样子)       wc.lpfnWndProc   = WndProc; // 消息处理函数       wc.cbClsExtra    = 0;       wc.cbWndExtra    = 0;       wc.hInstance     = hInstance; // 应用程序实例句柄       wc.hIcon         = LoadIcon(NULL,IDI_APPLICATION); // 装入图标       wc.hCursor       = LoadCursor(NULL,IDC_ARROW); // 装入鼠标箭头       wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // 选择窗口颜色(这里是白色)       wc.lpszMenuName  = NULL; // 没有菜单       wc.lpszClassName = "第一个 Windows 程序"; // 窗口所书属类名 将 WNDCLASS 结构填充好之后,还要注册一下。什么这还麻烦,你申请 EMAIL 的时候填完表格还要点击提交呢。注册函数为:         RegisterClass( &wc ); // 注册窗口类 注册完成之后就可以创建窗口了: ghWnd = CreateWindow( "第一个 Windows 程序", // 注册的窗口类名                     "第一个 Windows 程序", // 窗口条上显示的名字                    WS_OVERLAPPEDWINDOW, // 窗口风格                    0, // 显示窗口的左上角 X 坐标                    0, // 显示窗口的左上角 Y 坐标                    400, // 窗口宽度                    400, // 窗口高度                    NULL, // 是否有父窗口(这里设为没有)                    0, // 菜单句柄(这里设为没有)                    hInstance, // 程序实例句柄                    NULL ); // 设置为空 // 如果窗口创建失败就返回if( NULL == ghWnd )    return 0; 创建成功之后就会返回一个有效的窗口句柄,例子中的 ghWnd 就是用来保存窗口句柄的,由于该句柄在程序的整个运行过程中都是有效的,所以一定要是全局变量。如果创建窗口失败的话,就会返回空 NULL,没办法,只有退出了,什么,你不愿意退出,硬是要运行,那么 Windows 就硬是把你踢出来。     创建窗口完成之后就可以显示窗口了,调用下面两个函数就可以将创建好的窗口显示出来的:     ShowWindow( ghWnd, nCmdShow ); // 显示窗口    UpdateWindow( ghWnd ); // 更新窗口 最后一个附件就是创建消息循环了,在消息队列中检测消息,如果有消息的话就取出来,代码如下所示:该循环的退出条件是 Windows 系统向该窗口发送了退出消息。如果得到退出消息 GetMessage() 就返回0,否则返回非 0。退出该消息循环之后就退出了整个Windows 程序。     MSG msg;    while( 1 )    {       // 从消息队列中取消息       // TRUE - 取出一个消息       // FALSE - 退出消息循环       if( FALSE == GetMessage( &msg, NULL, 0, 0 ) )           return msg.wParam;        // 该函数翻译与键盘有关消息       TranslateMessage( &msg );       // 处理消息       DispatchMessage( &msg );   } 收
      

  3.   

    type
      EnumWindowsProc = function (Hwnd: THandle;
        Param: Pointer): Boolean; stdcall;function GetTitle (Hwnd: THandle; Param: Pointer): Boolean; stdcall;
    var
      Text: string;
    begin
      SetLength (Text, 100);
      GetWindowText (Hwnd, PChar (Text), 100);
      FormCallBack.ListBox1.Items.Add (
        IntToStr (Hwnd) + ': ' + Text);
      Result := True;
    end;procedure TFormCallback.BtnTitlesClick(Sender: TObject);
    var
      EWProc: EnumWindowsProc;
    begin
      ListBox1.Items.Clear;
      EWProc := GetTitle;
      EnumWindows (@EWProc, 0);
    end; 
     
    Billy (2000-04-20 18:36:00)  
    抄来的:
    type
      TCallBackFunction = function(s: string): integer;
      CallMe(s: string): integer;procedure TestCallBack(CallBackFunction: TCallBackFunction); far; external 'Other';
    { Note that 'other' is a Dll containing the procedure TestCallBack }function CallMe(s: PChar): integer;
    begin
      { what ever you need to do }
      CallMe := 1; { What ever you need to return }
    end;procedure TForm1.Button1Click(Sender: TObject);
    begin
      TestCallBack(CallMe);
    end;type
      TMainFunction = function(s: string): integer;
      TestCallBack(MainFunc: TMainFunction);
    { in library Other implementation }
    TestCallBack(MainFunc: TMainFunction);
    var
      result: integer;
    begin
      result:=MainFunc('test');
    end; 
      

  4.   

    谢谢各位了啊,但是如何判断一个函数指针是否为NIL呢?
    是不是:
    Result:=(NIL=@Function);