Как работать с последствиями WM_NCCALCSIZE ?

Тема в разделе "WASM.BEGINNERS", создана пользователем provocateur, 12 ноя 2010.

  1. provocateur

    provocateur Member

    Публикаций:
    0
    Регистрация:
    5 дек 2006
    Сообщения:
    118
    Я пытаюсь сделать элемент, который бы вел себя похоже на строку меню или панель инструментов. После их создания остальные окна размещаются ниже.

    У меня есть вот такая конструкция:

    Код (Text):
    1.         case WM_NCCALCSIZE:
    2.             RECT *prc;
    3.  
    4.             DefWindowProc ( hwnd, message, wParam, lParam );
    5.  
    6.             prc = (RECT *)lParam;
    7.  
    8.             prc->bottom-=20;
    9.         break;
    После этого в WM_SIZE приходит уменьшенный на двадцать HIWORD(lParam), и с его помощью все элементы могут "подтянуться" к новой высоте клиентской области.

    Но, в данном случае, внизу остается дырка. Ее нужно либо закрасить через WM_PAINT/WM_ERASEBKGND, либо через размещение поверх нее еще одного окна. Хотя желательно разобраться с обоими вариантами.

    Делать +20 к нужному окну не получается, клиентская область уменьшилась и дочернее окно просто не отображается.
    Прибавлять +20 внутри WM_PAINT или WM_ERASEBKGND к FillRect, например, тоже нельзя, не будет нужного эффекта. И, в принципе, понятно почему.
     
  2. tyug

    tyug New Member

    Публикаций:
    0
    Регистрация:
    26 окт 2008
    Сообщения:
    19
    WM_NCPAINT?
     
  3. provocateur

    provocateur Member

    Публикаций:
    0
    Регистрация:
    5 дек 2006
    Сообщения:
    118
    tyug, а как определить что именно нужно рисовать?
    или придется отрисовывать вообще все?
     
  4. KIV

    KIV Member

    Публикаций:
    0
    Регистрация:
    16 июл 2009
    Сообщения:
    231
    Никогда так не пробовал, но есть одна идея: а если не prc->bottom -=20, а prc->top += 20?
     
  5. tyug

    tyug New Member

    Публикаций:
    0
    Регистрация:
    26 окт 2008
    Сообщения:
    19
    provocateur
    Ну либо после стандартной обработки дорисовать что тебе требуется,
    либо вместо стандартной обработки отрисовать всю неклиентскую область.
     
  6. provocateur

    provocateur Member

    Публикаций:
    0
    Регистрация:
    5 дек 2006
    Сообщения:
    118
    KIV, тогда сверху отступ получается :)

    Сделал так:
    Код (Text):
    1. case WM_NCPAINT:
    2.     RECT rt;
    3.     hDC = GetWindowDC( hwnd );
    4.     GetClientRect ( hwnd, &rt );
    5.  
    6.     DefWindowProc ( hwnd, message, wParam, lParam );
    7.  
    8.     rt.left += GetSystemMetrics (SM_CXSIZEFRAME);
    9.     rt.right += GetSystemMetrics (SM_CXSIZEFRAME);
    10.     rt.top = rt.bottom + 20 + GetSystemMetrics (SM_CYSIZEFRAME) ;
    11.     rt.bottom = rt.top + 20;
    12.  
    13.     FillRect(hDC, &rt, GetSysColorBrush( COLOR_WINDOWFRAME ) );
    14.  
    15.     ReleaseDC ( hwnd, hDC );
    16. break;
    Вроде бы рисует (дорисовывает после системной ф-ции), но точно рассчитать область не могу. Не понимаю как оно действует. Вроде бы GetClientRect должно дать правильные данные, надо только сдвинуть влева на ширину рамки окна SM_CXSIZEFRAME (?). Но по высоте какой-то бардак. Вроде бы все понятно, что rt.top получится, если к получемнному через GetClientRect rt.bottom добавить высоту рамки SM_CYSIZEFRAME, а rt.bottom можно получить добавив в только что полученому tr.top 20 точек.
    Но при таком раскладе рисуется не то. В примере сначала к rt.bottom добавляю 20 и это становится топом, но ведь так не должно быть.
     
  7. provocateur

    provocateur Member

    Публикаций:
    0
    Регистрация:
    5 дек 2006
    Сообщения:
    118
    Кажется понял, забыл добавить высоту заголовка:

    Код (Text):
    1. rt.top = rt.bottom  + GetSystemMetrics (SM_CYSIZEFRAME)  + GetSystemMetrics (SM_CYCAPTION);
     
  8. provocateur

    provocateur Member

    Публикаций:
    0
    Регистрация:
    5 дек 2006
    Сообщения:
    118
    А теперь интересно, как в этой области разместить дочернее окно, если это вообще возможно.