【问题标题】:Deactivating desktop background when a pop up is shown to user向用户显示弹出窗口时停用桌面背景
【发布时间】:2013-04-19 18:50:33
【问题描述】:

我有一个启动时全屏运行的 win32 应用程序。该应用程序有一些按钮可以调用弹出对话框。

有没有办法让整个桌面(除了弹出窗口)变成透明黑色,除非弹出窗口被用户关闭?我所说的类似于 Windows 7 UAC 弹出窗口及其导致的背景。

是否可以为全屏窗口应用程序做类似的事情?

【问题讨论】:

  • 如何显示全屏始终在顶部的窗口?无论如何,我希望这是客户的要求,因为作为用户,我不喜欢这样做的应用程序。 :-)
  • 你能详细说明一下吗?你的意思是我创建一个窗口并将其隐藏,只有当对话框弹出时我才显示它?那会是一个什么样的窗口?

标签: windows winapi win32gui


【解决方案1】:

有可能这样做……有点。也许我应该说,你可以模拟这种效果。它实际上不会像 UAC 对话框那样,因为用户仍然能够与其他正在运行的应用程序进行交互。应用程序没有“系统模式”这样的概念。当然,这是设计使然。但是您当然可以显示一个“灯箱”,使桌面的其余部分变暗并强制将注意力集中在应用程序的对话框上。

我这样做的方法是创建一个巨大的layered window,它位于所有其他窗口的顶部并覆盖整个屏幕,用黑色填充它,并根据需要设置不透明度。然后,在显示模式对话框之前(通过调用 MessageBox 函数或使用 DialogBox 函数显示您自己的自定义对话框之一),显示您的灯箱窗口。最后,在用户关闭模态对话框后,您将销毁灯箱窗口。

这里有一些示例代码。为简洁起见,省略了错误检查。其他好的风格也是如此,比如将这个烂摊子包装在一个或多个类中。

INT_PTR ShowLightBoxedDialog(HINSTANCE hInstance,
                             LPCTSTR pDlgTemplate,
                             HWND hwndParent,
                             DLGPROC pDlgProc,
                             BYTE opacityLevel)
{
   const TCHAR szLightBoxClass[] = TEXT("LightBoxWndClass");

   // Register the light box window class.
   static bool lightBoxRegistered = false;
   if (!lightBoxRegistered)
   {
      WNDCLASSEX wcex;
      wcex.cbSize          = sizeof(wcex);
      wcex.style           = CS_NOCLOSE | CS_SAVEBITS;
      wcex.lpfnWndProc     = LightBoxWndProc;
      wcex.cbClsExtra      = 0;
      wcex.cbWndExtra      = 0;
      wcex.hInstance       = hInstance;
      wcex.hIcon           = NULL;
      wcex.hIconSm         = NULL;
      wcex.hCursor         = LoadCursor(NULL, IDC_ARROW);
      wcex.hbrBackground   = NULL;
      wcex.lpszMenuName    = NULL;
      wcex.lpszClassName   = szLightBoxClass;
      RegisterClassEx(&wcex);
      lightBoxRegistered = true;
   }

   // Create and display the light box window.
   HWND hwndLightBox = CreateWindowEx(WS_EX_NOACTIVATE | WS_EX_LAYERED,
                                      szLightBoxClass,
                                      NULL,
                                      WS_POPUPWINDOW,
                                      0, 0, 0, 0,
                                      hwndParent,
                                      NULL,
                                      hInstance,
                                      NULL);
   SetLayeredWindowAttributes(hwndLightBox, 0, opacityLevel, LWA_ALPHA);
   SetWindowPos(hwndLightBox,
                HWND_TOP,
                GetSystemMetrics(SM_XVIRTUALSCREEN),
                GetSystemMetrics(SM_YVIRTUALSCREEN),
                GetSystemMetrics(SM_CXVIRTUALSCREEN),
                GetSystemMetrics(SM_CYVIRTUALSCREEN),
                SWP_SHOWWINDOW);

   // Display the modal dialog box (as you normally would).
   // NOTE: The dialog box won't appear centered on the screen.
   // For that, you will need to write centering code in response
   // to the WM_INITDIALOG message in the dialog procedure.
   INT_PTR result = DialogBox(hInstance, pDlgTemplate, hwndLightBox, pDlgProc);
   // 
   // For demonstration purposes, I used the following code:
   // INT_PTR result = MessageBox(hwndLightBox,
   //                             TEXT("OH NOEZ!\n\nYour system is kaput! Abandon þe all hope."),
   //                             NULL,
   //                             MB_ABORTRETRYIGNORE | MB_ICONERROR);

   // Destroy the light box window.
   DestroyWindow(hwndLightBox);

   // Return the result of the modal dialog box.
   return result;
}

您会注意到,基本上我所做的是围绕DialogBox function 创建了一个包装器,只要您想要一个具有“灯箱”效果的对话框,就可以使用它。它采用所有相同的参数(前 4 个),然后在末尾添加一个额外的参数,允许您指定用于“灯箱”效果的不透明度级别。 150-200 范围内的东西可能是好的。当然,您可以选择一些东西并对其进行硬编码,但我对硬编码值严重过敏。不管怎样,从任何地方调用这个函数都超级容易:

ShowLightBoxedDialog(hInstance,                   /* your application instance */
                     MAKEINTRESOURCE(IDD_SAMPLE), /* your dialog template      */
                     hWnd,                        /* parent window for dialog  */
                     SampleWndProc,               /* ptr to dialog procedure   */
                     175);                        /* light box opacity level   */

由于代码利用了模式对话框在 Windows 中的工作方式,用户将无法与应用程序的任何其他部分进行交互,直到他们关闭对话框。而且因为“灯箱”窗口位于其他所有内容之上,它会吃掉所有鼠标点击并阻止将焦点设置到任何其他应用程序。但是使用 Alt+Tab 之类的东西是微不足道的。
所以这不是安全功能!这只是一种视觉效果!

而且因为它只是一种愚蠢的视觉效果,它可能会让您的用户感到沮丧。我实际上不建议使用它。但现在你知道该怎么做了。负责任地行使这种权力,等等。

【讨论】:

  • 这非常有帮助,我有这个想法,但不知道分层窗口和窗口不透明度。非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多