ShellExecuteEx и WaitForSingleObject рисуют повреждение окна под

Используя следующий код для обновления моего приложения внешним exe-файлом, я получаю повреждение краски (а не обновление или обновление) в окне, которое является основным приложением и вызывающей стороной, когда я перемещаю это окно. Кажется, что под Windows 7 работает нормально, но под Windows XP у меня есть эта проблема.

void CMainFrame::OnBtnUpdateApp() {

SHELLEXECUTEINFO    lpExecInfo;
DWORD               dwExitCode;
HINSTANCE           hProcess = 0;
BOOL                bResult;ZeroMemory(&lpExecInfo,sizeof(lpExecInfo));
lpExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
lpExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
lpExecInfo.hwnd = GetSafeHwnd();
lpExecInfo.lpVerb = _T("open");
lpExecInfo.lpFile = _T("Update.exe");
lpExecInfo.lpParameters = _T("");
lpExecInfo.lpDirectory = _T("");
lpExecInfo.nShow = SW_SHOWNORMAL;
lpExecInfo.hInstApp = NULL;
lpExecInfo.hProcess = hProcess;

bResult = ShellExecuteEx(&lpExecInfo);

if(bResult) {WaitForSingleObject( lpExecInfo.hProcess, INFINITE );

if (!GetExitCodeProcess(lpExecInfo.hProcess, &dwExitCode)) {
//failed to terminate normally
}

CloseHandle(lpExecInfo.hProcess);

} else {

//failed to execute the exe file
}}

Что здесь не так?

-1

Решение

Вы не обрабатываете никаких оконных сообщений во время WaitForSingleObject,

В отличие от Windows XP и Windows 7, Диспетчер окон рабочего стола Технология в Windows 7 была представлена ​​в Windows Vista и не была доступна в Windows XP. По сути, он обеспечивает слой косвенности между действиями рисования каждого приложения и результатом на экране.

Разумный способ запуска и ожидания программы — отключить главное окно части пользовательского интерфейса окна, а затем опрашивают состояние завершения программы в цикле просмотра сообщений.


Пример, кроме того, что он использует CreateProcess (Я закодировал его, не забывая проверить вопрос, и теперь уже довольно поздно вечером, но я думаю, что лучше с неполной помощью, чем без помощи):

#include <windows.h>    // UNICODE, NOMINMAX, STRICT, WIN32_LEAN_AND_MEAN
#include <windowsx.h>   // Message cracker macros, e.g. HANDLE_WM_DESTROY

#include <assert.h>
#include <stdexcept>
#include <string>
using namespace std;

auto hopefully( bool const condition ) -> bool { return condition; }
auto fail( string const& s ) -> bool { throw runtime_error( s ); }

struct Window_class_id
{
ATOM value;
auto as_pointer() const -> wchar_t const* { return MAKEINTATOM( value ); }
};

auto get_message( MSG& m )
-> bool
{
int const result = GetMessage( &m, 0, 0, 0 );
hopefully( result != -1 )
|| fail( "GetMessage failed" );
return !!result;
}

auto peek_message( MSG& m )
-> bool
{
int const result = PeekMessage( &m, 0, 0, 0, TRUE );
hopefully( result != -1 )
|| fail( "PeekMessage failed" );
return !!result;
}

void empty_message_queue()
{
MSG m;
while( peek_message( m ) )
{
TranslateMessage( &m );
DispatchMessage( &m );
}
}

auto dispatch_messages()
-> DWORD            // Exit code from WM_QUIT
{
MSG msg;
while( get_message( msg ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
assert( msg.message == WM_QUIT );
return msg.wParam;
}

auto run( wchar_t const command[] )
-> HANDLE
{
wstring commandline = command;
hopefully( commandline.length() > 0 )
|| fail( "run: Empty command line" );
STARTUPINFO in_params = { sizeof( STARTUPINFO ) };
PROCESS_INFORMATION out_params = {};

bool const success = !!CreateProcess(
nullptr,            // app name
&commandline[0],
nullptr,            // process attributes
nullptr,            // thread attributes
false,              // inherit handles
0,                  // creation flags
nullptr,            // environment block
nullptr,            // current directory
&in_params,         // startup info
&out_params         // process info
);
hopefully( success )
|| fail( "run: CreateProcess failed" );
CloseHandle( out_params.hThread );
return out_params.hProcess;
}

namespace main_window
{
namespace command_id {
int const run_fun = 101;
}  // namespace command

namespace run_button {
int const id     = command_id::run_fun;
}  // namespace run_button

namespace command {
void run_fun( HWND const window )
{
EnableWindow( GetDlgItem( window, run_button::id ), false );
UpdateWindow( window );
empty_message_queue();
HANDLE const process = run( L"notepad" );
for( ;; )
{
DWORD const result = WaitForSingleObject( process, 100 );
if( result == WAIT_OBJECT_0 )
{
break;
}
empty_message_queue();
}
CloseHandle( process );
EnableWindow( GetDlgItem( window, run_button::id ), true );
}
}  // namespace command

void on_command( HWND const window, int const id )
{
switch( id )
{
case command_id::run_fun:   return command::run_fun( window );
}
}

void on_wm_command(
HWND const      window,
int const       control_or_command_id,
HWND const      control,
UINT const      notification_code
)
{
if( control == 0 )
{
int const command_id = control_or_command_id;
on_command( window, command_id );
}
else
{
int const control_id = control_or_command_id;
switch( control_id )
{
case run_button::id:
if( notification_code == BN_CLICKED )
{
int const command_id = control_id;
on_command( window, command_id );
}
}
}
}

auto on_wm_create( HWND const window, CREATESTRUCT const* const p_params )
-> bool     // `true` if creation succeeded.
{
(void) p_params;
HWND const button_handle = CreateWindow(
L"button", L"Run the fun", WS_CHILD | WS_VISIBLE,
10, 10, 120, 26,
window,             // parent
reinterpret_cast<HMENU>( run_button::id ),
GetModuleHandle( 0 ),
0           // lpParam
);
return (button_handle != 0);
}

void on_wm_destroy( HWND const window )
{
(void) window;
PostQuitMessage( 0 );
}

auto CALLBACK message_handler(
HWND const          window,
UINT const          message_id,
WPARAM const        word_param,
LPARAM const        long_param
)
-> LRESULT
{
switch( message_id )
{
case WM_COMMAND:    return HANDLE_WM_COMMAND(
window, word_param, long_param, on_wm_command );
case WM_CREATE:     return HANDLE_WM_CREATE(
window, word_param, long_param, on_wm_create );
case WM_DESTROY:    return HANDLE_WM_DESTROY(
window, word_param, long_param, on_wm_destroy );
}
return DefWindowProc( window, message_id, word_param, long_param );
}
}  // namespace main_window

auto register_window_class()
-> Window_class_id
{
WNDCLASS params = {};
params.style            = CS_DBLCLKS;
params.lpfnWndProc      = main_window::message_handler;
params.hInstance        = GetModuleHandle( 0 );
params.hIcon            = LoadIcon( 0, IDI_APPLICATION );
params.hCursor          = LoadCursor( 0, IDC_ARROW );
params.hbrBackground    = reinterpret_cast<HBRUSH>( COLOR_WINDOW );
params.lpszClassName    = L"MainWindow_class";

ATOM const id = RegisterClass( &params );
hopefully( id != 0 )
|| fail( "RegisterClass failed" );
return {id};
}

auto create_window( Window_class_id const& class_id )
-> HWND
{
HWND const handle = CreateWindow(
class_id.as_pointer(),
L"Fun run",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 380, 221,     // x, y, w, h
0, 0,       // parent, menu
GetModuleHandle( 0 ),
0           // lpParam
);
hopefully( handle != 0 )
|| fail( "CreateWindow failed" );
return handle;
}

void cpp_main()
{
Window_class_id const class_id = register_window_class();
HWND const window = create_window( class_id );
ShowWindow( window, SW_SHOWDEFAULT );
int const exit_code = static_cast<int>( dispatch_messages() );
hopefully( exit_code == 0 )
|| fail( "WM_QUIT indicated failure" );
}

auto main() -> int
{
try{ cpp_main(); } catch( ... ) { return E_FAIL; }
return 0;
}
0

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

Других решений пока нет …

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