[MSGINA] Implement ShellDimScreen. CORE-11422

svn path=/trunk/; revision=72572
This commit is contained in:
Mark Jansen 2016-09-04 14:17:22 +00:00
parent 6a5543002e
commit 87a716926b
4 changed files with 289 additions and 13 deletions

View file

@ -1,11 +1,13 @@
set_cpp(WITH_RUNTIME)
include_directories(
include
${REACTOS_SOURCE_DIR}/sdk/lib/atl
${REACTOS_SOURCE_DIR}/sdk/include/reactos/wine)
spec2def(msgina.dll msgina.spec)
list(APPEND SOURCE
list(APPEND C_SOURCE
gui.c
lsa.c
msgina.c
@ -14,15 +16,19 @@ list(APPEND SOURCE
tui.c
msgina.h)
list(APPEND CPP_SOURCE
dimmedwindow.cpp)
add_library(msgina SHARED
${SOURCE}
${C_SOURCE}
${CPP_SOURCE}
msgina.rc
${CMAKE_CURRENT_BINARY_DIR}/msgina_stubs.c
${CMAKE_CURRENT_BINARY_DIR}/msgina.def)
set_module_type(msgina win32dll)
target_link_libraries(msgina wine)
set_module_type(msgina win32dll UNICODE)
target_link_libraries(msgina atlnew wine uuid ${PSEH_LIB})
add_delay_importlibs(msgina secur32)
add_importlibs(msgina advapi32 user32 gdi32 powrprof userenv msvcrt kernel32 ntdll)
add_pch(msgina msgina.h SOURCE)
add_pch(msgina msgina.h CPP_SOURCE)
add_cd_file(TARGET msgina DESTINATION reactos/system32 FOR all)

View file

@ -0,0 +1,269 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS msgina.dll
* FILE: dll/win32/msgina/dimmedwindow.cpp
* PURPOSE: Implementation of ShellDimScreen
* PROGRAMMER: Mark Jansen
*/
#define COM_NO_WINDOWS_H
#include "msgina.h"
#include <wingdi.h>
#include <atlbase.h>
#include <atlcom.h>
#include <pseh/pseh2.h>
CComModule gModule;
// Please note: The INIT_TIMER is a workaround because ReactOS does not redraw the desktop in time,
// so the start menu is still visible on the dimmed screen.
#define INIT_TIMER_ID 0x112233
#define FADE_TIMER_ID 0x12345
class CDimmedWindow :
public CComObjectRootEx<CComMultiThreadModelNoCS>,
IUnknown
{
private:
HWND m_hwnd;
HDC m_hdc;
HBITMAP m_hbitmap;
HGDIOBJ m_oldbitmap;
LONG m_width;
LONG m_height;
BITMAPINFO m_bi;
UCHAR* m_bytes;
int m_step;
static LRESULT WINAPI Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
public:
CDimmedWindow()
: m_hwnd(NULL)
, m_hdc(NULL)
, m_hbitmap(NULL)
, m_oldbitmap(NULL)
, m_width(0)
, m_height(0)
, m_bytes(NULL)
, m_step(0)
{
WNDCLASSEXW wndclass = {sizeof(wndclass)};
wndclass.lpfnWndProc = Proc;
wndclass.hInstance = hDllInstance;
wndclass.hCursor = LoadCursor(0, IDC_ARROW);
wndclass.lpszClassName = L"DimmedWindowClass";
if (!RegisterClassExW(&wndclass))
return;
m_width = GetSystemMetrics(SM_CXVIRTUALSCREEN);
m_height = GetSystemMetrics(SM_CYVIRTUALSCREEN);
memset(&m_bi, 0, sizeof(m_bi));
m_bi.bmiHeader.biSize = sizeof(m_bi);
m_bi.bmiHeader.biWidth = m_width;
m_bi.bmiHeader.biHeight = m_height;
m_bi.bmiHeader.biPlanes = 1;
m_bi.bmiHeader.biBitCount = 32;
m_bi.bmiHeader.biCompression = BI_RGB;
m_bi.bmiHeader.biSizeImage = m_width * 4 * m_height;
m_bytes = new UCHAR[m_width * 4 * m_height];
LONG x = GetSystemMetrics(SM_XVIRTUALSCREEN);
LONG y = GetSystemMetrics(SM_YVIRTUALSCREEN);
m_hwnd = CreateWindowExW(WS_EX_TOPMOST, L"DimmedWindowClass", NULL, WS_POPUP,
x, y, m_width, m_height,
NULL, NULL, hDllInstance, (LPVOID)this);
}
~CDimmedWindow()
{
if (m_hwnd)
DestroyWindow(m_hwnd);
UnregisterClassW(L"DimmedWindowClass", hDllInstance);
if (m_oldbitmap)
SelectObject(m_hdc, m_oldbitmap);
if (m_hbitmap)
DeleteObject(m_hbitmap);
if (m_hdc)
DeleteObject(m_hdc);
if (m_bytes)
delete[] m_bytes;
}
// This is needed so that we do not capture the start menu while it's closing.
void WaitForInit()
{
MSG msg;
while (!IsWindowVisible(m_hwnd))
{
while (::PeekMessage(&msg, m_hwnd, 0, 0, PM_REMOVE))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
if (IsWindowVisible(m_hwnd))
break;
}
}
}
void Init()
{
Capture();
ShowWindow(m_hwnd, SW_SHOWNA);
EnableWindow(m_hwnd, FALSE);
SetTimer(m_hwnd, FADE_TIMER_ID, 200, NULL);
}
void Capture()
{
HWND desktopWnd = GetDesktopWindow();
HDC desktopDC = GetDC(desktopWnd);
m_hdc = CreateCompatibleDC(desktopDC);
m_hbitmap = CreateCompatibleBitmap(desktopDC, m_width, m_height);
m_oldbitmap = SelectObject(m_hdc, m_hbitmap);
BitBlt(m_hdc, 0, 0, m_width, m_height, desktopDC, 0, 0, SRCCOPY);
ReleaseDC(desktopWnd, desktopDC);
}
bool Step()
{
// Stop after 10 steps
if (m_step++ > 10 || !m_bytes)
return false;
int lines = GetDIBits(m_hdc, m_hbitmap, 0, m_height, m_bytes, &m_bi, DIB_RGB_COLORS);
if (lines)
{
for (int xh = 0; xh < m_height; ++xh)
{
int h = m_width * 4 * xh;
for (int w = 0; w < m_width; ++w)
{
UCHAR b = m_bytes[(h + w * 4) + 0];
UCHAR g = m_bytes[(h + w * 4) + 1];
UCHAR r = m_bytes[(h + w * 4) + 2];
// Standard formula to convert a color.
int gray = (r * 30 + g * 59 + b * 11) / 100;
if (gray < 0)
gray = 0;
// Do not fade too fast.
r = (r*2 + gray) / 3;
g = (g*2 + gray) / 3;
b = (b*2 + gray) / 3;
m_bytes[(h + w * 4) + 0] = b;
m_bytes[(h + w * 4) + 1] = g;
m_bytes[(h + w * 4) + 2] = r;
}
}
SetDIBits(m_hdc, m_hbitmap, 0, lines, m_bytes, &m_bi, DIB_RGB_COLORS);
}
return true;
}
void Blt(HDC hdc)
{
BitBlt(hdc, 0, 0, m_width, m_height, m_hdc, 0, 0, SRCCOPY);
}
HWND Wnd()
{
return m_hwnd;
}
BEGIN_COM_MAP(CDimmedWindow)
COM_INTERFACE_ENTRY_IID(IID_IUnknown, IUnknown)
END_COM_MAP()
};
LRESULT WINAPI CDimmedWindow::Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_NCCREATE:
{
LPCREATESTRUCT lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam);
CDimmedWindow* info = static_cast<CDimmedWindow*>(lpcs->lpCreateParams);
SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG)info);
SetTimer(hWnd, INIT_TIMER_ID, 50, NULL);
break;
}
case WM_PAINT:
{
CDimmedWindow* info = reinterpret_cast<CDimmedWindow*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
if (info)
{
PAINTSTRUCT paint;
HDC hdc = BeginPaint(hWnd, &paint);
info->Blt(hdc);
EndPaint(hWnd, &paint);
}
return 0;
}
case WM_TIMER:
if (wParam == INIT_TIMER_ID)
{
CDimmedWindow* info = reinterpret_cast<CDimmedWindow*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
KillTimer(hWnd, INIT_TIMER_ID);
info->Init();
return 0;
}
if (wParam == FADE_TIMER_ID)
{
CDimmedWindow* info = reinterpret_cast<CDimmedWindow*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
if (info && info->Step())
InvalidateRect(hWnd, NULL, TRUE);
else
KillTimer(hWnd, FADE_TIMER_ID);
return 0;
}
break;
default:
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
extern "C"
HRESULT WINAPI
ShellDimScreen (void** pUnknown, HWND* hWindow)
{
CComObject<CDimmedWindow> *pWindow;
HRESULT hr = CComObject<CDimmedWindow>::CreateInstance(&pWindow);
ULONG refcount;
pWindow->WaitForInit();
_SEH2_TRY
{
hr = pWindow->QueryInterface(IID_IUnknown, pUnknown);
*hWindow = pWindow->Wnd();
hr = S_OK;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
hr = E_INVALIDARG;
refcount = pWindow->AddRef();
while (refcount)
refcount = pWindow->Release();
}
_SEH2_END
return hr;
}

View file

@ -1,6 +1,10 @@
#ifndef _MSGINA_H
#define _MSGINA_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdarg.h>
#define WIN32_NO_STATUS
@ -125,4 +129,8 @@ CreateProfile(
IN PWSTR Domain,
IN PWSTR Password);
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* _MSGINA_H */

View file

@ -116,10 +116,3 @@ WlxGetConsoleSwitchCredentials(
UNIMPLEMENTED;
return FALSE;
}
HRESULT WINAPI
ShellDimScreen (void* Unknown, HWND* hWindow)
{
UNIMPLEMENTED;
return E_FAIL;
}