ShellExecuteEx和WaitForSingleObject将损坏绘制到窗口下

时间:2016-02-14 11:13:33

标签: c++ mfc paint shellexecute waitforsingleobject

使用以下代码使用外部exe文件更新我的应用程序,当我移动此窗口时,我会将油漆损坏(不更新或刷新)到下面的窗口 - 它是主应用程序和调用者。似乎在Windows 7下工作正常但在窗口XP下我有这个问题。

docs-keys

这里看起来有什么问题?

1 个答案:

答案 0 :(得分:0)

您在WaitForSingleObject期间未处理任何窗口消息。

重新区分Windows XP和Windows 7,Windows 7中的Desktop Window Manager技术是在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;
}