mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Handle DisplayResolution scaling in windowed mode
This commit is contained in:
parent
fc16184256
commit
5ce5ea0668
@ -387,20 +387,19 @@ namespace D3dDdi
|
|||||||
void fixPresent(D3DKMT_PRESENT& data)
|
void fixPresent(D3DKMT_PRESENT& data)
|
||||||
{
|
{
|
||||||
static RECT rect = {};
|
static RECT rect = {};
|
||||||
if (DDraw::RealPrimarySurface::isFullscreen())
|
HWND devicePresentationWindow = DDraw::RealPrimarySurface::getDevicePresentationWindow();
|
||||||
|
HWND presentationWindow = DDraw::RealPrimarySurface::getPresentationWindow();
|
||||||
|
if (devicePresentationWindow && devicePresentationWindow == data.hWindow ||
|
||||||
|
presentationWindow && presentationWindow == data.hWindow)
|
||||||
{
|
{
|
||||||
HWND devicePresentationWindow = DDraw::RealPrimarySurface::getDevicePresentationWindow();
|
rect = DDraw::RealPrimarySurface::getMonitorRect();
|
||||||
if (devicePresentationWindow && devicePresentationWindow == data.hWindow)
|
OffsetRect(&rect, -rect.left, -rect.top);
|
||||||
|
data.SrcRect = rect;
|
||||||
|
data.DstRect.right = data.DstRect.left + rect.right;
|
||||||
|
data.DstRect.bottom = data.DstRect.top + rect.bottom;
|
||||||
|
if (1 == data.SubRectCnt)
|
||||||
{
|
{
|
||||||
rect = DDraw::RealPrimarySurface::getMonitorRect();
|
data.pSrcSubRects = ▭
|
||||||
OffsetRect(&rect, -rect.left, -rect.top);
|
|
||||||
data.SrcRect = rect;
|
|
||||||
data.DstRect.right = data.DstRect.left + rect.right;
|
|
||||||
data.DstRect.bottom = data.DstRect.top + rect.bottom;
|
|
||||||
if (1 == data.SubRectCnt)
|
|
||||||
{
|
|
||||||
data.pSrcSubRects = ▭
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,16 +131,7 @@ namespace D3dDdi
|
|||||||
|
|
||||||
if (m_origData.Flags.MatchGdiPrimary)
|
if (m_origData.Flags.MatchGdiPrimary)
|
||||||
{
|
{
|
||||||
g_presentationRect = calculatePresentationRect();
|
setFullscreenMode(true);
|
||||||
auto& si = m_origData.pSurfList[0];
|
|
||||||
RECT primaryRect = { 0, 0, static_cast<LONG>(si.Width), static_cast<LONG>(si.Height) };
|
|
||||||
|
|
||||||
Gdi::Cursor::setMonitorClipRect(DDraw::PrimarySurface::getMonitorRect());
|
|
||||||
if (!EqualRect(&g_presentationRect, &primaryRect))
|
|
||||||
{
|
|
||||||
Gdi::Cursor::setEmulated(true);
|
|
||||||
}
|
|
||||||
Gdi::VirtualScreen::setFullscreenMode(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fixResourceData();
|
fixResourceData();
|
||||||
@ -180,9 +171,7 @@ namespace D3dDdi
|
|||||||
{
|
{
|
||||||
if (m_origData.Flags.MatchGdiPrimary)
|
if (m_origData.Flags.MatchGdiPrimary)
|
||||||
{
|
{
|
||||||
Gdi::VirtualScreen::setFullscreenMode(false);
|
setFullscreenMode(false);
|
||||||
Gdi::Cursor::setEmulated(false);
|
|
||||||
Gdi::Cursor::setMonitorClipRect({});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_msaaSurface.surface || m_msaaResolvedSurface.surface || m_lockRefSurface.surface)
|
if (m_msaaSurface.surface || m_msaaResolvedSurface.surface || m_lockRefSurface.surface)
|
||||||
@ -1036,6 +1025,7 @@ namespace D3dDdi
|
|||||||
|
|
||||||
HRESULT Resource::presentationBlt(D3DDDIARG_BLT data, Resource* srcResource)
|
HRESULT Resource::presentationBlt(D3DDDIARG_BLT data, Resource* srcResource)
|
||||||
{
|
{
|
||||||
|
LOG_FUNC("Resource::presentationBlt", data, *srcResource);
|
||||||
if (srcResource->m_lockResource)
|
if (srcResource->m_lockResource)
|
||||||
{
|
{
|
||||||
if (srcResource->m_lockData[data.SrcSubResourceIndex].isSysMemUpToDate &&
|
if (srcResource->m_lockData[data.SrcSubResourceIndex].isSysMemUpToDate &&
|
||||||
@ -1066,7 +1056,7 @@ namespace D3dDdi
|
|||||||
srcResource = repo.getTempTexture(srcWidth, srcHeight, getPixelFormat(srcResource->m_fixedData.Format)).resource;
|
srcResource = repo.getTempTexture(srcWidth, srcHeight, getPixelFormat(srcResource->m_fixedData.Format)).resource;
|
||||||
if (!srcResource)
|
if (!srcResource)
|
||||||
{
|
{
|
||||||
return E_OUTOFMEMORY;
|
return LOG_RESULT(E_OUTOFMEMORY);
|
||||||
}
|
}
|
||||||
copySubResourceRegion(*srcResource, 0, data.SrcRect, data.hSrcResource, data.SrcSubResourceIndex, data.SrcRect);
|
copySubResourceRegion(*srcResource, 0, data.SrcRect, data.hSrcResource, data.SrcSubResourceIndex, data.SrcRect);
|
||||||
}
|
}
|
||||||
@ -1103,7 +1093,7 @@ namespace D3dDdi
|
|||||||
|
|
||||||
if (!rtSurface.resource)
|
if (!rtSurface.resource)
|
||||||
{
|
{
|
||||||
return S_OK;
|
return LOG_RESULT(S_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
const LONG dstWidth = data.DstRect.right - data.DstRect.left;
|
const LONG dstWidth = data.DstRect.right - data.DstRect.left;
|
||||||
@ -1147,7 +1137,7 @@ namespace D3dDdi
|
|||||||
}
|
}
|
||||||
|
|
||||||
clearRectExterior(data.DstSubResourceIndex, data.DstRect);
|
clearRectExterior(data.DstSubResourceIndex, data.DstRect);
|
||||||
return S_OK;
|
return LOG_RESULT(S_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Resource::presentLayeredWindows(Resource& dst, UINT dstSubResourceIndex, const RECT& dstRect)
|
void Resource::presentLayeredWindows(Resource& dst, UINT dstSubResourceIndex, const RECT& dstRect)
|
||||||
@ -1244,6 +1234,35 @@ namespace D3dDdi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Resource::setFullscreenMode(bool isFullscreen)
|
||||||
|
{
|
||||||
|
if (!IsRectEmpty(&g_presentationRect) == isFullscreen)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isFullscreen)
|
||||||
|
{
|
||||||
|
g_presentationRect = calculatePresentationRect();
|
||||||
|
auto& si = m_origData.pSurfList[0];
|
||||||
|
RECT primaryRect = { 0, 0, static_cast<LONG>(si.Width), static_cast<LONG>(si.Height) };
|
||||||
|
|
||||||
|
Gdi::Cursor::setMonitorClipRect(DDraw::PrimarySurface::getMonitorRect());
|
||||||
|
if (!EqualRect(&g_presentationRect, &primaryRect))
|
||||||
|
{
|
||||||
|
Gdi::Cursor::setEmulated(true);
|
||||||
|
}
|
||||||
|
Gdi::VirtualScreen::setFullscreenMode(m_origData.Flags.MatchGdiPrimary);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_presentationRect = {};
|
||||||
|
Gdi::VirtualScreen::setFullscreenMode(false);
|
||||||
|
Gdi::Cursor::setEmulated(false);
|
||||||
|
Gdi::Cursor::setMonitorClipRect({});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
HRESULT Resource::shaderBlt(D3DDDIARG_BLT& data, Resource& dstResource, Resource& srcResource)
|
HRESULT Resource::shaderBlt(D3DDDIARG_BLT& data, Resource& dstResource, Resource& srcResource)
|
||||||
{
|
{
|
||||||
LOG_FUNC("Resource::shaderBlt", data, srcResource);
|
LOG_FUNC("Resource::shaderBlt", data, srcResource);
|
||||||
|
@ -49,6 +49,7 @@ namespace D3dDdi
|
|||||||
void scaleRect(RECT& rect);
|
void scaleRect(RECT& rect);
|
||||||
void setAsGdiResource(bool isGdiResource);
|
void setAsGdiResource(bool isGdiResource);
|
||||||
void setAsPrimary();
|
void setAsPrimary();
|
||||||
|
void setFullscreenMode(bool isFullscreen);
|
||||||
HRESULT unlock(const D3DDDIARG_UNLOCK& data);
|
HRESULT unlock(const D3DDDIARG_UNLOCK& data);
|
||||||
void updateConfig();
|
void updateConfig();
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include <Gdi/Gdi.h>
|
#include <Gdi/Gdi.h>
|
||||||
#include <Gdi/GuiThread.h>
|
#include <Gdi/GuiThread.h>
|
||||||
#include <Gdi/Palette.h>
|
#include <Gdi/Palette.h>
|
||||||
|
#include <Gdi/PresentationWindow.h>
|
||||||
#include <Gdi/VirtualScreen.h>
|
#include <Gdi/VirtualScreen.h>
|
||||||
#include <Gdi/Window.h>
|
#include <Gdi/Window.h>
|
||||||
#include <Gdi/WinProc.h>
|
#include <Gdi/WinProc.h>
|
||||||
@ -62,6 +63,7 @@ namespace
|
|||||||
HWND g_devicePresentationWindow = nullptr;
|
HWND g_devicePresentationWindow = nullptr;
|
||||||
HWND g_deviceWindow = nullptr;
|
HWND g_deviceWindow = nullptr;
|
||||||
HWND* g_deviceWindowPtr = nullptr;
|
HWND* g_deviceWindowPtr = nullptr;
|
||||||
|
HWND g_presentationWindow = nullptr;
|
||||||
|
|
||||||
CompatPtr<IDirectDrawSurface7> getBackBuffer();
|
CompatPtr<IDirectDrawSurface7> getBackBuffer();
|
||||||
CompatPtr<IDirectDrawSurface7> getLastSurface();
|
CompatPtr<IDirectDrawSurface7> getLastSurface();
|
||||||
@ -195,6 +197,16 @@ namespace
|
|||||||
{
|
{
|
||||||
LOG_FUNC("RealPrimarySurface::onRelease");
|
LOG_FUNC("RealPrimarySurface::onRelease");
|
||||||
|
|
||||||
|
if (g_presentationWindow)
|
||||||
|
{
|
||||||
|
auto resource = D3dDdi::Device::findResource(
|
||||||
|
DDraw::DirectDrawSurface::getDriverResourceHandle(*g_windowedBackBuffer));
|
||||||
|
resource->setFullscreenMode(false);
|
||||||
|
|
||||||
|
Gdi::GuiThread::destroyWindow(g_presentationWindow);
|
||||||
|
g_presentationWindow = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
g_frontBuffer = nullptr;
|
g_frontBuffer = nullptr;
|
||||||
g_lastFlipSurface = nullptr;
|
g_lastFlipSurface = nullptr;
|
||||||
g_windowedBackBuffer.release();
|
g_windowedBackBuffer.release();
|
||||||
@ -296,6 +308,44 @@ namespace
|
|||||||
g_presentEndVsyncCount = D3dDdi::KernelModeThunks::getVsyncCounter() + 1;
|
g_presentEndVsyncCount = D3dDdi::KernelModeThunks::getVsyncCounter() + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updatePresentationWindowPos()
|
||||||
|
{
|
||||||
|
if (!g_presentationWindow)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isFullscreen = false;
|
||||||
|
if (SUCCEEDED(g_frontBuffer->IsLost(g_frontBuffer)))
|
||||||
|
{
|
||||||
|
HWND foregroundWindow = GetForegroundWindow();
|
||||||
|
if (foregroundWindow)
|
||||||
|
{
|
||||||
|
DWORD pid = 0;
|
||||||
|
GetWindowThreadProcessId(foregroundWindow, &pid);
|
||||||
|
isFullscreen = GetCurrentProcessId() == pid && Gdi::Window::hasFullscreenWindow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto resource = D3dDdi::Device::findResource(
|
||||||
|
DDraw::DirectDrawSurface::getDriverResourceHandle(*g_windowedBackBuffer));
|
||||||
|
resource->setFullscreenMode(isFullscreen);
|
||||||
|
|
||||||
|
Gdi::GuiThread::execute([&]()
|
||||||
|
{
|
||||||
|
if (isFullscreen)
|
||||||
|
{
|
||||||
|
CALL_ORIG_FUNC(SetWindowPos)(g_presentationWindow, HWND_TOPMOST, g_monitorRect.left, g_monitorRect.top,
|
||||||
|
g_monitorRect.right - g_monitorRect.left, g_monitorRect.bottom - g_monitorRect.top,
|
||||||
|
SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_NOREDRAW | SWP_NOOWNERZORDER | SWP_SHOWWINDOW);
|
||||||
|
}
|
||||||
|
else if (IsWindowVisible(g_presentationWindow))
|
||||||
|
{
|
||||||
|
ShowWindow(g_presentationWindow, SW_HIDE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
unsigned WINAPI updateThreadProc(LPVOID /*lpParameter*/)
|
unsigned WINAPI updateThreadProc(LPVOID /*lpParameter*/)
|
||||||
{
|
{
|
||||||
int msUntilUpdateReady = 0;
|
int msUntilUpdateReady = 0;
|
||||||
@ -311,6 +361,7 @@ namespace
|
|||||||
}
|
}
|
||||||
|
|
||||||
DDraw::ScopedThreadLock lock;
|
DDraw::ScopedThreadLock lock;
|
||||||
|
updatePresentationWindowPos();
|
||||||
msUntilUpdateReady = DDraw::RealPrimarySurface::flush();
|
msUntilUpdateReady = DDraw::RealPrimarySurface::flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -363,9 +414,19 @@ namespace DDraw
|
|||||||
g_frontBuffer->SetPrivateData(g_frontBuffer, IID_IReleaseNotifier,
|
g_frontBuffer->SetPrivateData(g_frontBuffer, IID_IReleaseNotifier,
|
||||||
&g_releaseNotifier, sizeof(&g_releaseNotifier), DDSPD_IUNKNOWNPOINTER);
|
&g_releaseNotifier, sizeof(&g_releaseNotifier), DDSPD_IUNKNOWNPOINTER);
|
||||||
|
|
||||||
g_deviceWindowPtr = DDraw::DirectDraw::getDeviceWindowPtr(dd.get());
|
g_deviceWindowPtr = (0 != desc.dwBackBufferCount) ? DDraw::DirectDraw::getDeviceWindowPtr(dd.get()) : nullptr;
|
||||||
g_deviceWindow = g_deviceWindowPtr ? *g_deviceWindowPtr : nullptr;
|
g_deviceWindow = g_deviceWindowPtr ? *g_deviceWindowPtr : nullptr;
|
||||||
g_devicePresentationWindow = Gdi::Window::getPresentationWindow(g_deviceWindow);
|
g_devicePresentationWindow = g_deviceWindow ? Gdi::Window::getPresentationWindow(g_deviceWindow) : nullptr;
|
||||||
|
|
||||||
|
if (0 == desc.dwBackBufferCount)
|
||||||
|
{
|
||||||
|
auto mr = DDraw::PrimarySurface::getMonitorRect();
|
||||||
|
if (!EqualRect(&mr, &g_monitorRect))
|
||||||
|
{
|
||||||
|
g_presentationWindow = Gdi::PresentationWindow::create(nullptr);
|
||||||
|
updatePresentationWindowPos();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onRestore();
|
onRestore();
|
||||||
updateDevicePresentationWindowPos();
|
updateDevicePresentationWindowPos();
|
||||||
@ -484,6 +545,11 @@ namespace DDraw
|
|||||||
return g_monitorRect;
|
return g_monitorRect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HWND RealPrimarySurface::getPresentationWindow()
|
||||||
|
{
|
||||||
|
return g_presentationWindow;
|
||||||
|
}
|
||||||
|
|
||||||
CompatWeakPtr<IDirectDrawSurface7> RealPrimarySurface::getSurface()
|
CompatWeakPtr<IDirectDrawSurface7> RealPrimarySurface::getSurface()
|
||||||
{
|
{
|
||||||
return g_frontBuffer;
|
return g_frontBuffer;
|
||||||
@ -495,6 +561,10 @@ namespace DDraw
|
|||||||
{
|
{
|
||||||
return g_devicePresentationWindow;
|
return g_devicePresentationWindow;
|
||||||
}
|
}
|
||||||
|
if (g_presentationWindow && IsWindowVisible(g_presentationWindow))
|
||||||
|
{
|
||||||
|
return g_presentationWindow;
|
||||||
|
}
|
||||||
return HWND_TOPMOST;
|
return HWND_TOPMOST;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -576,7 +646,7 @@ namespace DDraw
|
|||||||
|
|
||||||
Gdi::GuiThread::execute([&]()
|
Gdi::GuiThread::execute([&]()
|
||||||
{
|
{
|
||||||
if (g_isFullscreen && IsWindowVisible(g_deviceWindow) && !IsIconic(g_deviceWindow))
|
if (IsWindowVisible(g_deviceWindow) && !IsIconic(g_deviceWindow))
|
||||||
{
|
{
|
||||||
CALL_ORIG_FUNC(SetWindowPos)(g_devicePresentationWindow, HWND_TOPMOST, g_monitorRect.left, g_monitorRect.top,
|
CALL_ORIG_FUNC(SetWindowPos)(g_devicePresentationWindow, HWND_TOPMOST, g_monitorRect.left, g_monitorRect.top,
|
||||||
g_monitorRect.right - g_monitorRect.left, g_monitorRect.bottom - g_monitorRect.top,
|
g_monitorRect.right - g_monitorRect.left, g_monitorRect.bottom - g_monitorRect.top,
|
||||||
|
@ -18,6 +18,7 @@ namespace DDraw
|
|||||||
static HRESULT flip(CompatPtr<IDirectDrawSurface7> surfaceTargetOverride, DWORD flags);
|
static HRESULT flip(CompatPtr<IDirectDrawSurface7> surfaceTargetOverride, DWORD flags);
|
||||||
static int flush();
|
static int flush();
|
||||||
static HWND getDevicePresentationWindow();
|
static HWND getDevicePresentationWindow();
|
||||||
|
static HWND getPresentationWindow();
|
||||||
static HRESULT getGammaRamp(DDGAMMARAMP* rampData);
|
static HRESULT getGammaRamp(DDGAMMARAMP* rampData);
|
||||||
static RECT getMonitorRect();
|
static RECT getMonitorRect();
|
||||||
static CompatWeakPtr<IDirectDrawSurface7> getSurface();
|
static CompatWeakPtr<IDirectDrawSurface7> getSurface();
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <D3dDdi/KernelModeThunks.h>
|
#include <D3dDdi/KernelModeThunks.h>
|
||||||
#include <D3dDdi/ScopedCriticalSection.h>
|
#include <D3dDdi/ScopedCriticalSection.h>
|
||||||
#include <DDraw/RealPrimarySurface.h>
|
#include <DDraw/RealPrimarySurface.h>
|
||||||
|
#include <DDraw/Surfaces/PrimarySurface.h>
|
||||||
#include <Gdi/Gdi.h>
|
#include <Gdi/Gdi.h>
|
||||||
#include <Gdi/GuiThread.h>
|
#include <Gdi/GuiThread.h>
|
||||||
#include <Gdi/PresentationWindow.h>
|
#include <Gdi/PresentationWindow.h>
|
||||||
@ -419,6 +420,26 @@ namespace Gdi
|
|||||||
return layeredWindows;
|
return layeredWindows;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool hasFullscreenWindow()
|
||||||
|
{
|
||||||
|
D3dDdi::ScopedCriticalSection lock;
|
||||||
|
RECT mr = DDraw::PrimarySurface::getMonitorRect();
|
||||||
|
for (auto& window : g_windows)
|
||||||
|
{
|
||||||
|
if (!window.second.isLayered &&
|
||||||
|
window.second.windowRect.left <= mr.left &&
|
||||||
|
window.second.windowRect.top <= mr.top &&
|
||||||
|
window.second.windowRect.right >= mr.right &&
|
||||||
|
window.second.windowRect.bottom >= mr.bottom &&
|
||||||
|
IsWindowVisible(window.first) &&
|
||||||
|
!IsIconic(window.first))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool isTopLevelWindow(HWND hwnd)
|
bool isTopLevelWindow(HWND hwnd)
|
||||||
{
|
{
|
||||||
return GetDesktopWindow() == GetAncestor(hwnd, GA_PARENT);
|
return GetDesktopWindow() == GetAncestor(hwnd, GA_PARENT);
|
||||||
@ -492,6 +513,14 @@ namespace Gdi
|
|||||||
CompatRef<IDirectDrawClipper> clipper)
|
CompatRef<IDirectDrawClipper> clipper)
|
||||||
{
|
{
|
||||||
D3dDdi::ScopedCriticalSection lock;
|
D3dDdi::ScopedCriticalSection lock;
|
||||||
|
auto presentationWindow = DDraw::RealPrimarySurface::getPresentationWindow();
|
||||||
|
if (presentationWindow && IsWindowVisible(presentationWindow))
|
||||||
|
{
|
||||||
|
clipper->SetHWnd(&clipper, 0, presentationWindow);
|
||||||
|
dst->Blt(&dst, nullptr, &src, nullptr, DDBLT_WAIT, nullptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (auto window : g_windowZOrder)
|
for (auto window : g_windowZOrder)
|
||||||
{
|
{
|
||||||
if (window->presentationWindow && !window->visibleRegion.isEmpty())
|
if (window->presentationWindow && !window->visibleRegion.isEmpty())
|
||||||
|
@ -19,6 +19,7 @@ namespace Gdi
|
|||||||
|
|
||||||
HWND getPresentationWindow(HWND hwnd);
|
HWND getPresentationWindow(HWND hwnd);
|
||||||
std::vector<LayeredWindow> getVisibleLayeredWindows();
|
std::vector<LayeredWindow> getVisibleLayeredWindows();
|
||||||
|
bool hasFullscreenWindow();
|
||||||
bool isTopLevelWindow(HWND hwnd);
|
bool isTopLevelWindow(HWND hwnd);
|
||||||
void onStyleChanged(HWND hwnd, WPARAM wParam);
|
void onStyleChanged(HWND hwnd, WPARAM wParam);
|
||||||
void onSyncPaint(HWND hwnd);
|
void onSyncPaint(HWND hwnd);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user