枚举窗口时可以考虑的一些简化策略

来源:互联网 发布:sql查询 编辑:程序博客网 时间:2024/05/17 16:45

BOOL EnumWindows(  WNDENUMPROC lpEnumFunc,  // callback function
   LPARAM lParam            // application-defined value
   );
执行EnumWindows时,User32.dll会把传递进来的lpEnumFunc和lParam记录下来,然后开始遍历所有顶层

窗口。每找到一个窗口,user32.dll就把这个窗口的句柄跟lParam传递给回调函数lpEnumFunc并执行它。

lpEnumFunc是自定义的一个函数,它明显体现了应用程序跟操作系统交互的现象。如果lpEnumFunc返回

true则user32.dll会继续遍历窗口,如果lpEnumFunc返回false则user32.dll停止遍历窗口,EnumWindows

的任务也就完成了(否则直到所有窗口被遍历完)。
lpEnumFunc的声明形式是这样的:
BOOL __stdcall EnumProc( HWND  hWnd, LPARAM parameter );


// test in vc++8.0
// stdafx.h里面: #include <stdio.h> #include <tchar.h>
/// 核心代码在于EnumWindows的回调函数。

#include "stdafx.h"

#include <windows.h>

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);

static int  nFlag = 0;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int

iCmdShow)
{
    static TCHAR szAppName[] = TEXT ("bluesky_class");
    HWND         hwnd;
    MSG          msg;
    WNDCLASSEX   wndclassex = {0};
    wndclassex.cbSize        = sizeof(WNDCLASSEX);
    wndclassex.style         = CS_HREDRAW | CS_VREDRAW;
    wndclassex.lpfnWndProc   = WndProc;
    wndclassex.cbClsExtra    = 0;
    wndclassex.cbWndExtra    = 0;
    wndclassex.hInstance     = hInstance;
    wndclassex.hIcon         = LoadIcon (NULL, IDI_APPLICATION);
    wndclassex.hCursor       = LoadCursor (NULL, IDC_ARROW);
    wndclassex.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
    wndclassex.lpszMenuName  = NULL;
    wndclassex.lpszClassName = szAppName;
    wndclassex.hIconSm       = wndclassex.hIcon;
 
    if (!RegisterClassEx (&wndclassex))
    {
        MessageBox (NULL, TEXT ("RegisterClassEx failed!"), szAppName, MB_ICONERROR);
        return 0;
    }

    hwnd = CreateWindowEx (WS_EX_OVERLAPPEDWINDOW,
                    szAppName,
                    TEXT ("bluesky"),
                    WS_OVERLAPPEDWINDOW,
                    CW_USEDEFAULT,
                    CW_USEDEFAULT,
                    CW_USEDEFAULT,
                    CW_USEDEFAULT,
                    NULL,
                    NULL,
                    hInstance,
                    NULL);
       
    ShowWindow (hwnd, iCmdShow);
    UpdateWindow (hwnd);
 
    while (GetMessage (&msg, NULL, 0, 0))
    {
        TranslateMessage (&msg);
        DispatchMessage (&msg);
    }

    return msg.wParam;
}

BOOL __stdcall EveryWindowProc( HWND  hWnd, LPARAM parameter );

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    HDC hdc;
    PAINTSTRUCT ps;
 TCHAR  info[] = TEXT( "press left mouse!" );

    switch (message)
    {
    case WM_CREATE:
        return (0);
 
    case WM_PAINT:
        hdc = BeginPaint (hwnd, &ps);
        TextOut (hdc, 100, 100, info, wcslen(info) );
        EndPaint (hwnd, &ps);
        return (0);
 
    case WM_DESTROY:
        PostQuitMessage (0);
        return (0);

 case WM_LBUTTONDOWN:
  EnumWindows( EveryWindowProc, (LPARAM)0 );
  if ( nFlag == 0 )
   nFlag = 1;
  else if ( nFlag == 1 )
   nFlag = 0;

  break;
    }

    return DefWindowProc (hwnd, message, wParam, lParam);
}

// 以下代码抄了网上的
BOOL __stdcall EveryWindowProc(HWND hWnd, LPARAM parameter )
{
 // 不可见、不可激活的窗口不作考虑。

 if ( !IsWindowVisible(hWnd) )
  return TRUE;

 if ( !IsWindowEnabled(hWnd) )
  return TRUE;

 // 弹出式窗口,但没有标题的不作考虑。
 LONG gwl_style = GetWindowLong( hWnd, GWL_STYLE );
 if ((gwl_style & WS_POPUP) && !(gwl_style & WS_CAPTION))
  return TRUE;

 // 父窗口是可见或可激活的窗口不作考虑。
 HWND hParent = (HWND)GetWindowLong( hWnd, GWL_HWNDPARENT );
 if ( IsWindowEnabled(hParent) )
  return TRUE;
 if ( IsWindowVisible(hParent) )
  return TRUE;

 // Shell_TrayWnd类的窗口(托盘里面的)不作考虑。
 TCHAR szClassName[MAX_PATH];
 GetClassName( hWnd, szClassName, MAX_PATH );
 if ( !wcscmp(szClassName, _T("Shell_TrayWnd")) )
  return TRUE;


 if ( nFlag == 0 )
 {
  // 最小化
  CloseWindow( hWnd );
 }
 else
 {
  // 激活并恢复原大小及位置
  OpenIcon( hWnd );
 }

 return TRUE;
}