TPopupMenu прорисовка рамки
От: Flamer Кипр http://users.livejournal.com/_flamer_/
Дата: 24.06.04 11:54
Оценка:
Есть owner-draw попап-меню. Все итемы рисуются ручками. Также перерисовывается стандартная рамка всего окна попап-меню и делается плоской. Примерно так:
   // Draw menu border
  HWND mWnd = WindowFromDC(ACanvas->Handle);

  if(mWnd != Handle)
  {
    TCanvas* cTemp = new TCanvas;
    cTemp->Handle = GetDC(0);
    TRect rMenu;
    GetWindowRect(mWnd, &rMenu);

    cTemp->Brush->Color = TColor(RGB(120, 120, 120));
    cTemp->FrameRect(rMenu);

    InflateRect(&rMenu, -1, -1);
    cTemp->Brush->Color = TColor(RGB(240, 240, 240));
    cTemp->FrameRect(rMenu);

    InflateRect(&rMenu, -1, -1);
    cTemp->FrameRect(rMenu);

    ReleaseDC(0, cTemp->Handle);
    delete cTemp;
  }  // if(mWnd != Handle)


Под WinXP все шоколадно, а вот под Win2000 окно меню при всплывании имеет стандартный объемный вид до тех пор, пока по нему мышой не проведешь. Как только провели мышой над итемом — окно становится плоским, как и надо.

Вопрос: как вылечить это дело? Поиск по группогуглю облегчения не принес.
Re: TPopupMenu прорисовка рамки
От: AlexEagle Украина http://www.vik.oil
Дата: 24.06.04 15:25
Оценка: 12 (1)
Здравствуйте, Flamer, Вы писали:

F>Под WinXP все шоколадно, а вот под Win2000 окно меню при всплывании имеет стандартный объемный вид до тех пор, пока по нему мышой не проведешь. Как только провели мышой над итемом — окно становится плоским, как и надо.


F>Вопрос: как вылечить это дело? Поиск по группогуглю облегчения не принес.



Попробуй поискать в сырцах XPMenu — компонента для делфи — Там в версии >> 3 эта проблема решена (если не ошибаюсь перехватывается создание окна для меню и там вручную все с ним творится)
Re: TPopupMenu прорисовка рамки
От: Flamer Кипр http://users.livejournal.com/_flamer_/
Дата: 24.06.04 18:51
Оценка: 19 (3)
Здравствуйте, Flamer, Вы писали:

[]

F>Под WinXP все шоколадно, а вот под Win2000 окно меню при всплывании имеет стандартный объемный вид до тех пор, пока по нему мышой не проведешь. Как только провели мышой над итемом — окно становится плоским, как и надо.


Вот, вылечилось. Может, кому и пригодится (спасибо AlexEagle за наводку). Работает в Win2000 и в WinXP. Делает плоским любое popup-меню. Мне многого было не нужно, поэтому код — минимальный... Да, забыл сказать — чтобы это добро работало, меню должно быть owner-drawn (проперть OwnerDraw = true и обработчик события OnDrawItem/OnAdvancedDrawItem для пунктов меню)... В общем, все по порядку (пример для билдера):

В хидере:
//---------------------------------------------------------------------------
#define WM_DRAWMENUBORDER (WM_USER + 10)
//---------------------------------------------------------------------------
class TfmMain : public TForm
{
__published:
    void __fastcall FormCreate(TObject *Sender); // OnCreate формы
    void __fastcall FormDestroy(TObject *Sender); // OnDestroy формы

    void __fastcall Item21DrawItem(TObject *Sender, TCanvas *ACanvas,
          TRect &ARect, bool Selected); // обработчик рисования пункта меню

private:    // User declarations

    bool __fastcall OnDrawMenuBorder(TMessage& Message); // хук-функция
    void __fastcall DrawWindowBorder(HWND hWnd); // рисование плоской рамки

};


Сорц:
void __fastcall TfmMain::FormCreate(TObject *Sender)
{
Application->HookMainWindow(OnDrawMenuBorder);
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::FormDestroy(TObject *Sender)
{
Application->UnhookMainWindow(OnDrawMenuBorder);
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::Item21DrawItem(TObject *Sender, TCanvas *ACanvas,
      TRect &ARect, bool Selected)
{
   // просто выводим текст для пункта меню...
   ACanvas->TextRect(ARect,ARect.Left,ARect.Top,((TMenuItem*)Sender)->Caption);

   // посылаем сообщение аппликации...
   MSG msg;
   if(!PeekMessage(&msg,Application->Handle,WM_DRAWMENUBORDER,WM_DRAWMENUBORDER,PM_NOREMOVE))
   {
     PostMessage(Application->Handle,WM_DRAWMENUBORDER,0,(LPARAM)Sender);
   }
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::DrawWindowBorder(HWND hWnd)
{
 // прорисовываем рамку меню...
 if(IsWindowVisible(hWnd) && hWnd != Handle)
  {
    TCanvas* cTemp = new TCanvas;
    cTemp->Handle = GetDC(0);
    TRect rMenu;
    GetWindowRect(hWnd, &rMenu);

    cTemp->Brush->Color = TColor(RGB(120, 120, 120));
    cTemp->FrameRect(rMenu);

    InflateRect(&rMenu, -1, -1);
    cTemp->Brush->Color = TColor(RGB(240, 240, 240));
    cTemp->FrameRect(rMenu);

    InflateRect(&rMenu, -1, -1);
    cTemp->FrameRect(rMenu);

    ReleaseDC(0, cTemp->Handle);
    delete cTemp;
  }  // if(hWnd != Handle)

}
//---------------------------------------------------------------------------
bool __fastcall TfmMain::OnDrawMenuBorder(TMessage& Message)
{

if(Message.Msg == WM_DRAWMENUBORDER) // пришло наше сообщение
{
  TMenuItem*  FMenuItem = (TMenuItem*) Message.LParam;
     TRect r;
     GetMenuItemRect(0,FMenuItem->Parent->Handle,FMenuItem->MenuIndex,&r);
     TPoint pt; pt.x=r.Left+(r.Right-r.Left) / 2;
     pt.y =r.Top+(r.Bottom-r.Top) / 2;

     HWND hWndM = WindowFromPoint(pt); // ищем окно меню

     if(hWndM)
       DrawWindowBorder(hWndM); // рисуем ему рамку...

}
return false;
}
//---------------------------------------------------------------------------


Все оказалось достаточно просто...
Re[2]: TPopupMenu прорисовка рамки
От: AlexEagle Украина http://www.vik.oil
Дата: 24.06.04 19:16
Оценка:
Здравствуйте, Flamer, Вы писали:

Если доделаешь стиль Оффис2003 — мое мыло всегда открыто для твоего компонента

P.S. Я сейчас юзаю переделанный мною XPMenu (доделал нормальное отображение градиента да и по мелочам много). Но тяжела вещь
Re[2]: TPopupMenu прорисовка рамки
От: ArtDenis Россия  
Дата: 25.06.04 04:05
Оценка:
Здравствуйте, Flamer, Вы писали:

F> Вот, вылечилось. Может, кому и пригодится (спасибо AlexEagle за

F> наводку). Работает в Win2000 и в WinXP. ...



Я решил реализовать это в виде компонента.
Posted via RSDN NNTP Server 1.9 beta
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re[3]: TPopupMenu прорисовка рамки
От: ArtDenis Россия  
Дата: 25.06.04 04:10
Оценка:
PS: запостил бы ты это в форум "исходники".
Posted via RSDN NNTP Server 1.9 beta
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re[4]: TPopupMenu прорисовка рамки
От: Flamer Кипр http://users.livejournal.com/_flamer_/
Дата: 25.06.04 06:32
Оценка:
Здравствуйте, ArtDenis, Вы писали:

AD>PS: запостил бы ты это в форум "исходники".


Сей момент
Re[2]: TPopupMenu прорисовка рамки
От: AndrewJD США  
Дата: 18.04.05 11:56
Оценка:
Здравствуйте, Flamer, Вы писали:

F>Вот, вылечилось. Может, кому и пригодится (спасибо AlexEagle за наводку). Работает в Win2000 и в WinXP. Делает плоским любое popup-меню. Мне многого было не нужно, поэтому код — минимальный... Да, забыл сказать — чтобы это добро работало, меню должно быть owner-drawn (проперть OwnerDraw = true и обработчик события OnDrawItem/OnAdvancedDrawItem для пунктов меню)... В общем, все по порядку (пример для билдера):


F>Все оказалось достаточно просто...


Не работает этот метод под Win2000 Server (под остальные не пробывал). Т.е. работает но криво с миганием.

Проблема в следующем:
После создания окна меню и первой орисовки, винда насильно перерисовывает рамку . Исследования показали, что это происходит после первой отрисовки и посылания сообщения WM_ENTERIDLE. Если в обработчике WM_ENTERIDLE снова запостить сообщение для перерисовки рамки — рамка затирается как надо, но это визуально видно (Вначале прорисовывается стандартная рамка и спустя некоторе время моя).

Какие есть идеи?
"For every complex problem, there is a solution that is simple, neat,
and wrong."
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.