Окно Win32 зависает после первого розыгрыша (directx 11)

У меня есть стандартное окно win32, на котором я рисую D2D1, Все отзывчиво и работает без сбоев. Моя проблема заключается в следующем: после того, как окно создано, оно вызывает WM_PAINT один раз и затем застревает в ожидании любого пользовательского ввода (ех. переместите или щелкните мышью в области окна). Получив ввод, он работает без каких-либо проблем. Хотя это не обязательно делает программу нефункциональной, она кажется крайне непрофессиональной и … уродливый. О, и что я подразумеваю под «зависанием», так это то, что фоновые процессы по-прежнему выполняются без проблем, поэтому цикл выполняется так, как задумано — однако WM_PAINT не вызывается по какой-то причине.

Вот текущий код:

заголовочный файл:

#define PROGRAM_FPS 30
#define GWINDOW_STYLE (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_CLIPCHILDREN | WS_CLIPSIBLINGS)

class Application
{
public:
Application();
~Application();

// Register the window class and call methods for instantiating drawing resources
HRESULT Initialize();

// Process and dispatch messages
void RunMessageLoop();

static inline void SafeRelease(IUnknown * _X)
{
if(_X != NULL)
_X->Release();
};

HRESULT SetFullscreen(bool);

private:

// Time (ms) between frames of the application
// Initiation: m_AppFPS_Div( (DWORD)1000.0 / (DWORD)PROGRAM_FPS )
const DWORD m_AppFPS_Div;

// Initialize device-independent resources.
HRESULT CreateDeviceIndependentResources();

// Initialize device-dependent resources.
HRESULT CreateDeviceResources();

// Release device-dependent resource.
void DiscardDeviceResources();

// Draw content.
HRESULT OnRender();

HRESULT LoadBitmapFromFile(
ID2D1RenderTarget*,
PCWSTR,
UINT,
UINT,
ID2D1Bitmap **
);

// The windows procedure.
static LRESULT CALLBACK WndProc(
HWND hWnd,
UINT message,
WPARAM wParam,
LPARAM lParam
);
HWND m_hwnd;
ID2D1Factory * m_pDirect2dFactory;
ID2D1HwndRenderTarget * m_pRenderTarget;
IWICImagingFactory *m_pIWICFactory;
ID2D1SolidColorBrush * m_pWhiteBrush;
ID2D1SolidColorBrush * m_pGrayBrush;
ID2D1LinearGradientBrush * m_pLinearGradientBrush;
ID2D1Bitmap *m_LoadingPicture;
};

части файла .cpp

void Application::RunMessageLoop()
{
HACCEL hAccelTable = LoadAccelerators(hInst, MAKEINTRESOURCE(IDC_WIN32APP));
DWORD screen_last_refresh = 0;
MSG msg;
for(bool applicationRunning = true; applicationRunning;)
{
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if(msg.message == WM_QUIT)
{
applicationRunning = false;
}

if(!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}

/*** HERE I RUN VARIOUS BACKGROUND PROCESSES ***/

while((GetTickCount() - screen_last_refresh) < m_AppFPS_Div)
Sleep(2);
InvalidateRect(msg.hwnd, NULL, false);
screen_last_refresh = GetTickCount();
}
}

LRESULT CALLBACK Application::WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
LRESULT result = 0;
if (message == WM_CREATE)
{
LPCREATESTRUCT pcs = (LPCREATESTRUCT)lParam;
Application *pApp = (Application *)pcs->lpCreateParams;

::SetWindowLongPtrW(hwnd, GWLP_USERDATA, PtrToUlong(pApp) );
InvalidateRect(hwnd, NULL, false);
result = 1;
}
else
{
Application *pApp = reinterpret_cast<Application *>(static_cast<LONG_PTR>(
::GetWindowLongPtrW(
hwnd,
GWLP_USERDATA
)));

bool wasHandled = false;

if (pApp)
{
switch (message)
{
case WM_SIZE:
{
UINT width = LOWORD(lParam);
UINT height = HIWORD(lParam);
pApp->OnResize(width, height);
}
result = 0;
wasHandled = true;
break;

case WM_DISPLAYCHANGE:
{
InvalidateRect(hwnd, NULL, FALSE);
}
result = 0;
wasHandled = true;
break;

case WM_PAINT:
{
pApp->OnRender();
ValidateRect(hwnd, NULL);
}
result = 0;
wasHandled = true;
break;

case WM_DESTROY:
{
PostQuitMessage(0);
}
result = 1;
wasHandled = true;
break;
}
}

if (!wasHandled)
{
result = DefWindowProc(hwnd, message, wParam, lParam);
}
}
return result;
}

HRESULT Application::OnRender()
{
HRESULT hr = S_OK;
hr = CreateDeviceResources();
if (SUCCEEDED(hr))
{
m_pRenderTarget->BeginDraw();
m_pRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity());

/** HERE I HANDLE THE OPENING ANIMATION **/

hr = m_pRenderTarget->EndDraw();
}

if (hr == D2DERR_RECREATE_TARGET)
{
hr = S_OK;
DiscardDeviceResources();
}
return hr;
}

Итак, я протестировал его на 2 компьютерах (оба с Win 8.1) с VS 2012 Ultimate и VS 2013 Professional, запускал отладочные тесты назад и вперед, разбирал определенные части программы, искал MDSN, Google и StackExchange — безрезультатно. Это замораживание также происходит, когда я справляюсь WM_COMMAND детского окна. Когда я пытался внедрить GDI +, такой проблемы также не было, но она оказалась крайне неэффективной, что привело к переходу на DirectX. Кроме того, программа работает без нареканий. Я надеюсь, что предоставил достаточно информации.

0

Решение

Вам не ясно, что вы делаете для запуска «различных фоновых процессов». Вероятно, отсюда и возникает «застрявшая» проблема. Предложение состоит в том, чтобы убрать это из цикла сообщений. Вместо этого вызывайте SetTimer во время инициализации окна, а затем выполняйте небольшую часть фонового процесса каждый раз, когда приходит сообщение WM_TIMER.

И, когда вы хотите, чтобы WM_PAINT пришел, вызовите InvalidateRect ().

0

Другие решения


По вопросам рекламы [email protected]