2013-08-12 2 views
3

У меня есть главное окно, которое создается с помощью следующих стилей
WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU | WS_TABSTOP | WS_GROUP | WS_VISIBLE
и с бывшим stles
WS_EX_ACCEPTFILES | WS_EX_CONTROLPARENT | WS_EX_LEFT | WS_EX_LTRREADING.Как рисовать дочернее окно с помощью FillRect()?

Это главное окно имеет дочернее окно на нем, который является элемент управления редактированием, созданное с стилями
WS_VISIBLE | WS_CHILD | ES_READONLY
и экс-стилем
WS_EX_CLIENTEDGE.

Я собираюсь использовать этот элемент управления редактирования в качестве регулятора хода выполнения. Я не хочу использовать стандартный контроль выполнения Wind32 (PROGRESS_CLASS), потому что я хочу сделать на нем какую-то пользовательскую картину (например, динамическое изменение цвета заливки, отображение текста на нем и т. Д.).

Я могу нарисовать любую область главного окна следующим кодом:

// hWnd: Handle of the main window 
case WM_PAINT: 
    hDc = BeginPaint(hWnd, &Ps); 
     Rect = AFunctionToGetCornerThePointsOfTheEditControl(); 
     Rect.right = Rect.left + 3 * (Rect.right - Rect.left)/4; // Fill 3/4 (75%) of it 
     Rect.left -= 10; // Enlarge the paint region a little 
     Rect.top -= 10; // so that we can see it if it stays 
     Rect.bottom += 10; // under the edit control. 
     hBrush = CreateSolidBrush(RGB(50,100,255)); 
     ret = FillRect(hDc, &Rect, hBrush); // ret = 1 always 
     ler = GetLastError();    // ler = 0 
    EndPaint(hWnd, &Ps); 
    break; 

Это выглядит следующим образом:
appearance of the painted window

Я изменил этот код немного окрасить дочерний элемент управления, вместо этого:

// hWndEdit: Handle of the edit control 
case WM_PAINT: 
    hDc = BeginPaint(hWndEdit, &Ps); 
     Rect = AFunctionToGetCornerThePointsOfTheEditControl(); 
     Rect.right = Rect.left + 3 * (Rect.right - Rect.left)/4; // Fill 3/4 (75%) of it 
     Rect.left -= 10; 
     Rect.top -= 10; 
     Rect.bottom += 10; 
     hBrush = CreateSolidBrush(RGB(50,100,255)); 
     ret = FillRect(hDc, &Rect, hBrush); // ret = 0 always 
     ler = GetLastError();    // ler = 6 (ERROR_INVALID_HANDLE) 
    EndPaint(hWndEdit, &Ps); 
    break; 

На этот раз это не сработает. Основные окна полностью исчезают, как только я вывожу какую-то часть из области экрана, и он становится полностью невосприимчивым. Значки рабочего стола под ним видны, но не доступны.

Итак, что мне нужно сделать, чтобы нарисовать дочернее окно (элемент управления редактированием)?

+0

Правильный способ сделать обычную покраску - подклассифицировать ее. – chris

ответ

-1

WM_PAINT, с которым вы работаете, является основным окном. вам нужно нарисовать окно редактирования в сообщении владельца WM_PAINT. Я думаю, вы получите сообщение об ошибке «hDc = BeginPaint (hWndEdit, & Ps)», вы можете проверить его.

1

Эта статья помогла мне много: Subclassing Controls

Первый, я создаю отдельную функцию обработки сообщений для обработки дочерних сообщений.

LRESULT CALLBACK MyClass::ChildWindowProc( HWND  hWnd, 
              UINT  uMsg, 
              WPARAM  wParam, 
              LPARAM  lParam, 
              UINT_PTR uIdSubclass, 
              DWORD_PTR dwRefData) 
{ 
    static PAINTSTRUCT Ps; 
    static RECT Rect; 
    static HBRUSH hBrush1 = CreateSolidBrush(RGB(50,100,255)); 
    static HBRUSH hBrush2 = CreateSolidBrush(RGB(255,100,50)); 
    HDC hDc; 
    LRESULT lResult; 
    switch (uMsg) 
    { 
     case WM_PAINT: 
      switch (uIdSubclass) 
      { 
       case 1: 
        hDc = BeginPaint(hWnd, &Ps); 
         Rect.left = 0; 
         Rect.right = (LONG) (((double) ITEM2_WIDTH) * Status::GI()->Get_JobCurPercentage()); 
         Rect.top = 0; 
         Rect.bottom = ITEM_HEIGHT - 3; 
         FillRect(hDc, &Rect, hBrush1); 
        EndPaint(hWnd, &Ps); 
        break; 
       case 2: 
        hDc = BeginPaint(hWnd, &Ps); 
         Rect.left = 0; 
         Rect.right = (LONG) (((double) ITEM2_WIDTH) * Status::GI()->Get_JobTotPercentage()); 
         Rect.top = 0; 
         Rect.bottom = ITEM_HEIGHT - 3; 
         FillRect(hDc, &Rect, hBrush2); 
        EndPaint(hWnd, &Ps); 
        break; 
       default: 
        return DefSubclassProc(hWnd, uMsg, wParam, lParam); 
      } 
      break; 
     case WM_NCDESTROY: 
      //ReleaseDC(hWnd, hDc); 
      return DefSubclassProc(hWnd, uMsg, wParam, lParam); 
      break; 
     default: 
      return DefSubclassProc(hWnd, uMsg, wParam, lParam); 
    } 
    return 0; 
} 

Далее, я связываю эту функцию для управления:

SetWindowSubclass( /*_In_ HWND   hWnd*/   ed_cur_Progress.hWnd, 
        /*_In_ SUBCLASSPROC pfnSubclass*/ ChildWindowProc, 
        /*_In_ UINT_PTR  uIdSubclass*/ 1, 
        /*_In_ DWORD_PTR  dwRefData*/  (DWORD_PTR) NULL); 
SetWindowSubclass( /*_In_ HWND   hWnd*/   ed_tot_Progress.hWnd, 
        /*_In_ SUBCLASSPROC pfnSubclass*/ ChildWindowProc, 
        /*_In_ UINT_PTR  uIdSubclass*/ 2, 
        /*_In_ DWORD_PTR  dwRefData*/  (DWORD_PTR) NULL); 

И это все! Результат потрясающий.

appearance

+0

Контекст устройства, возвращаемый из 'BeginPaint', не должен быть передан, вызывая' ReleaseDC'. Хуже всего то, что вы передаете неинициализированную переменную «HDC» в 'ReleaseDC' в обработчик' WM_DESTROY'. Еще одно примечание по очистке: 'WM_NCDESTROY' - это окончательное сообщение, отправленное в окно. Здесь вы должны поместить свой код очистки. – IInspectable

+0

@Tim Спасибо за информацию; Я поменяю свой код в соответствии с ним. Как мне изменить контекст устройства? Выпустить его в первую очередь? – hkBattousai

+0

Ресурсы, связанные с контекстом устройства, возвращаемые из 'BeginPaint', будут выпущены системой при вызове' EndPaint'. Я понимаю, что оставлять «болтающийся» HDC выглядит неправильно, но это не так.Для справки см. [Рисование в клиентской области] (http://msdn.microsoft.com/en-us/library/windows/desktop/dd162487.aspx). – IInspectable

Смежные вопросы