⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 voyeur.dpr

📁 这一系列是我平时收集的pascal深入核心编程
💻 DPR
字号:
program Voyeur;

{$R Voyeur.res}

uses Windows, Messages, VoyHelp in 'VoyHelp.pas';

const
  IDI_VOYEUR = 102; // 图标资源ID
  IDC_EYES = 103;   // 光标资源ID
  IDC_WNDINFO = 1000; // 编辑框ID

  // WM_CREATE 消息处理函数
function Voyeur_OnCreate(hWnd: HWND; lpCreateStruct: PCreateStruct): Boolean;
var
  hWndEdit: LongWord; // HWND
  uTabStop: UINT;
begin
 // 建立编辑控件
  hWndEdit := CreateWindowEx(0, 'EDIT',
    'Click and drag the right mouse button to select a window.',
    WS_CHILD or WS_HSCROLL or WS_VSCROLL or WS_VISIBLE or ES_AUTOHSCROLL or
    ES_AUTOVSCROLL or ES_LEFT or ES_MULTILINE or ES_READONLY,
    0, 0, 0, 0, hWnd, IDC_WNDINFO, HInstance, nil);

 // 如果建立成功   
  if (hWndEdit <> 0) then
  begin
   // 设置统一的 tab stops , 使得文本格式整齐
   // 采用Dialog单位(大约是字符平均宽度的1/4)
    uTabStop := 4 * 20;
    SendMessage(hWndEdit, EM_SETTABSTOPS, 1, Integer(@uTabStop));
  end;

 // 是否建立成功
  Result := (hWndEdit <> 0);
end;

  // WM_SIZE 消息处理过程
procedure Voyeur_OnSize(hWnd: HWND; state: UINT; cx, cy: Integer);
begin
 // 使编辑框充满窗体
  SetWindowPos(GetDlgItem(hWnd, IDC_WNDINFO), 0, 0, 0, cx, cy, SWP_NOZORDER);
end;

  // WM_PARENTNOTIFY 消息处理过程
procedure Voyeur_OnParentNotify(hWnd: HWND; Msg: UINT; hWndChild: HWND; idChild: Integer);
begin
 // 当用户在编辑框控件按下鼠标右键,
 // 系统会发WM_PARENTNOTIFY消息通知主窗体
 // 此时, 程序开始进入'窥视'状态 ..
  if (Msg = WM_RBUTTONDOWN) then
  begin
   // 自身置于 window manager’s list 的最底端
    SetWindowPos(hWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE);

   // 强制所有鼠标消息都只发送给本窗口
    SetCapture(hWnd);

   // 设置鼠标光标为'眼睛', 表明正在'窥视'..
    SetCursor(LoadCursor(HInstance, MakeIntResource(IDC_EYES)));

   // 最后被选择的窗体的句柄, 保存在本窗体实例的额外内存
   // 现在, 先将其初始化为 0
    SetWindowLong(hWnd, 0, 0);
  end;
end;

  // WM_MOUSEMOVE 消息处理过程
procedure Voyeur_OnMouseMove(hWnd: HWND; x, y: Integer; keyFlags: UINT);
var
  dwMousePos: DWORD;
  ptMouse: TPoint;
  hWndSubject: LongWord; // HWND
  hWndLastSubject: LongWord; // HWND
begin
 // 如果此过程被调用, 应该是由于SetCapture(hWnd),
 // 因为平时鼠标移动消息总是只送给前面的编辑控件

 // 取得最后一次取出消息时光标在屏幕上的位置(接近于当前位置),
 // 注意, 不要使用x和y参数, 因为它是针对hWnd客户区的相对坐标
  dwMousePos := GetMessagePos();

 // 取出上一个被选择的窗体句柄
  hWndLastSubject := GetWindowLong(hWnd, 0);

 // 取得当前鼠标所指的窗体句柄
  ptMouse.x := LOWORD(dwMousePos);
  ptMouse.y := HIWORD(dwMousePos);
  hWndSubject := WindowFromPoint(ptMouse);

 // 如果鼠标指向的是自己的窗体, 则不处理
  if (GetWindowThreadProcessId(hWndSubject, nil) = GetCurrentThreadId()) then Exit;

 // 如果和上一个被选择的窗体是同一个, 也不处理
  if (hWndLastSubject = hWndSubject) then Exit;

 // 恢复上次被选择的窗体的边框
  if (hWndLastSubject <> 0) then
    VoyHelp_DrawWindowFrame(hWndLastSubject);

 // 反转本次被选择的窗体的边框
  VoyHelp_DrawWindowFrame(hWndSubject);

 // 在编辑框控件内显示此窗体信息
  VoyHelp_UpdateWindowInfo(GetDlgItem(hWnd, IDC_WNDINFO), hWndSubject);

 // 新的被选窗体句柄保存至额外空间
  SetWindowLong(hWnd, 0, hWndSubject);
end;

  // WM_CAPTURECHANGED 消息处理过程
procedure Voyeur_OnCaptureChanged(hWnd, hWndNewCapture: HWND);
var
  hWndLastSubject: LongWord; // HWND
begin
  hWndLastSubject := GetWindowLong(hWnd, 0);

 // 当失去鼠标捕获, 如果之前仍有窗体被反转边框, 则..
  if (hWndLastSubject <> 0) then
  begin
    VoyHelp_DrawWindowFrame(hWndLastSubject); // 恢复最后被选择的窗体边框
    BringWindowToTop(hWnd); // 自身提至 window manager’s list 顶端
  end;

  SetWindowLong(hWnd, 0, 0);
end;

  // WM_RBUTTONUP 消息处理过程
procedure Voyeur_OnRButtonUp(hWnd: HWND; x, y: Integer; keyFlags: UINT);
begin
 // 如果此过程被调用, 应该是由于 SetCapture(),
 // 因为平时鼠标抬起消息总是送给前面的编辑框

 // 取消鼠标捕获, 使其他窗口可以正常收到鼠标消息
  ReleaseCapture();
end;

  // WM_QUERYENDSESSION 消息处理过程
function Voyeur_OnQueryEndSession(hWnd: HWND): Boolean;
var
  fIsDataUnsaved, fOKToEndSession: Boolean;
  n: Integer;
begin
 // 此处演示, 如果是关闭前需要保存数据的程序,
 // 应该如何正确处理, 即使是由关机导致的关闭

  fIsDataUnsaved := TRUE; // 数据未保存
  fOKToEndSession := TRUE; // 允许关闭

  if (fIsDataUnsaved) then
  begin
    n := MessageBox(hWnd, 'Do you want to save changes?', // 保存提示对话框
     'Voyeur - Example technique for proper shutdown', MB_YESNOCANCEL or MB_ICONWARNING);

    if (n = IDYES) then // 需要保存
    begin
      // 可以在此处弹出文件保存对话框, 比如 n := GetOpenFileName() ..
    end;

    if (n = IDCANCEL) then fOKToEndSession := FALSE; // 不许关闭
  end;

  Result := fOKToEndSession;
end;

  // WM_ENDSESSION 消息处理过程
procedure Voyeur_OnEndSession(hWnd: HWND; fEnding: BOOL);
begin
  if (fEnding) then DestroyWindow(hWnd); // 系统即将关闭, 则注销窗体

  // DestroyWindow()会发送WM_DESTROY和WM_NCDESTROY两个消息给窗体过程
end;

  // WM_DESTROY 消息处理过程
procedure Voyeur_OnDestroy(hWnd: HWND);
begin
 // 注意, 系统会自动注销hWnd的子窗体编辑框控件

 // 通知消息循环结束, 之后线程和进程也随即结束
  PostQuitMessage(0);
end;

  // WM_CLOSE 消息处理过程
procedure Voyeur_OnClose(hWnd: HWND);
begin
 // 与关机或注销同样的处理
  Voyeur_OnEndSession(hWnd, Voyeur_OnQueryEndSession(hWnd));
end;

  // 主窗体消息处理回调函数
function Voyeur_WndProc(hWnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
  Result := 0;
  
  case (uMsg) of
    WM_CREATE:
      if Voyeur_OnCreate(hWnd, PCreateStruct(lParam)) = FALSE then Result := -1;

    WM_SIZE:
      Voyeur_OnSize(hWnd, wParam, LOWORD(lParam), HIWORD(lParam));

    WM_PARENTNOTIFY:
      Voyeur_OnParentNotify(hWnd, LOWORD(wParam), lParam, HIWORD(wParam));

    WM_MOUSEMOVE:
      Voyeur_OnMouseMove(hWnd, LOWORD(lParam), HIWORD(lParam), wParam);

    WM_RBUTTONUP:
      Voyeur_OnRButtonUp(hWnd, LOWORD(lParam), HIWORD(lParam), wParam);

    WM_CAPTURECHANGED:
      Voyeur_OnCaptureChanged(hWnd, lParam);

    WM_CLOSE:
      Voyeur_OnClose(hWnd);

    WM_DESTROY:
      Voyeur_OnDestroy(hWnd);

    WM_QUERYENDSESSION:
      Result := Integer(Voyeur_OnQueryEndSession(hWnd));

    WM_ENDSESSION:
      Voyeur_OnEndSession(hWnd, BOOL(wParam));

    else
      Result := DefWindowProc(hWnd, uMsg, wParam, lParam);
  end;
end;

  // 程序'主线程'入口
var
  wc: TWndClassEx;
  atomClassNameVoyeur: ATOM;
  hWndMain: HWND;
  Msg: TMsg;
begin
 // 填充类结构
  ZeroMemory(@wc, SizeOf(TWndClassEx));
  wc.cbSize := SizeOf(TWndClassEx);
  wc.lpfnWndProc := @Voyeur_WndProc;
  wc.cbWndExtra := SizeOf(HWND); // 窗体额外空间保存最后选择的窗体的句柄
  wc.hInstance := HInstance;
  wc.hIcon := LoadIcon(HInstance, MakeIntreSource(IDI_VOYEUR));
  wc.hCursor := LoadCursor(0, IDC_ARROW);
  wc.lpszClassName := 'Voyeur';
  wc.hIconSm := wc.hIcon;

 // 注册窗体类
  atomClassNameVoyeur := RegisterClassEx(wc);
  if (atomClassNameVoyeur = INVALID_ATOM) then Exit;

 // 建立主窗体
  hWndMain := CreateWindowEx(0, MakeIntAtom(atomClassNameVoyeur),
    'Voyeur', WS_OVERLAPPEDWINDOW or WS_VISIBLE, Integer(CW_USEDEFAULT),
    SW_SHOW, // 注意: 当x为CW_USEDEFAULT, 此参数将作为隐含调用的ShowWindow()的参数
    Integer(CW_USEDEFAULT), 0, 0, 0, HInstance, nil);

 // 是窗体句柄   
  if IsWindow(hWndMain) then
  begin
    while GetMessage(Msg, 0, 0, 0) do // 循环, 直至取出 WM_QUIT
    begin
      TranslateMessage(Msg); // 转换消息
      DispatchMessage(Msg);  // 分发消息
    end;
  end;

 // 注销窗体类 
  UnregisterClass(MakeIntAtom(atomClassNameVoyeur), HInstance);
end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -