Модераторы: Snowy, bartram, MetalFan, bems, Poseidon, Riply

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как рисовать картинки в пунктах меню 
:(
    Опции темы
Nikfel
  Дата 16.7.2009, 16:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 15.7.2009
Где: Kirov

Репутация: нет
Всего: нет



У меня лежит меню в ресурсах. Загружаю его так:

Код

SetMenu(hwin,LoadMenu(HInstance, 'MAINMENU'));


Я понял как обработать сообщение WM_MeasureItem и WM_DrawItem, просто надо сначала для пункта меню сделать так:
Код

var h,h1:HMenu;
begin
h :=GetMenu(hwin);
h1 :=GetSubMenu(h,0);
ModifyMenu(h1,0,mf_ByPosition or mf_OwnerDraw,1001,'');


Можно ли поставить (mf_ByPosition or mf_OwnerDraw) через SetWindowLong?
Тогда окно будет получать сообщения WM_MeasureItem и WM_DrawItem, но проблема в том как нарисовать на меню, а точнее никак не получается получить HDC для пункта меню, чтобы рисовать на нем. 

В интернете найти не смог, т.к. там все плохие варианты предлагают, а мне надо на чистом Winapi.

Может кто знает как осуществить такое? Заранее спасибо.
PM MAIL   Вверх
Romikgy
Дата 16.7.2009, 19:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Любитель-программер
****


Профиль
Группа: Участник Клуба
Сообщений: 7326
Регистрация: 11.5.2005
Где: Porto Franco Odes sa

Репутация: 13
Всего: 146



Цитата(Nikfel @  16.7.2009,  15:33 Найти цитируемый пост)
там все плохие варианты предлагают

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


--------------------
Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. 
smile

PM   Вверх
Nikfel
Дата 16.7.2009, 20:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 15.7.2009
Где: Kirov

Репутация: нет
Всего: нет



И как же тогда перевести вот этот код на чистый WinApi:
http://delphisite.ru/faq/kak-risovat-karti...-punktakh-menyu

В основном в интернете я натыкался на подобный код через:
Procedure WMDrawItem(var Msg:TWMDrawItem); message wm_DrawItem;
Procedure WMMeasureItem(var Msg:TWMMeasureItem); message wm_MeasureItem;

Но на чистом WinApi делается по другому.
PM MAIL   Вверх
kami
Дата 16.7.2009, 20:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 15
Всего: 72



Цитата(Nikfel @  16.7.2009,  20:11 Найти цитируемый пост)
Но на чистом WinApi делается по другому.

По другому - это как?
там что, сообщения другие приходят?
Да, обработчик не будет классовым методом. Но это ничего не меняет.
PM MAIL WWW   Вверх
Nikfel
Дата 16.7.2009, 21:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 15.7.2009
Где: Kirov

Репутация: нет
Всего: нет



Код

var DIS:DRAWITEMSTRUCT;
...
WM_DrawItem:begin


Проблема в том как записать переменную DIS? Чтобы можно было получить DIS.HDC, чтобы рисовать на нем. Знаю что надо брать lParam, но как его записать в DIS?
PM MAIL   Вверх
Romikgy
Дата 16.7.2009, 21:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Любитель-программер
****


Профиль
Группа: Участник Клуба
Сообщений: 7326
Регистрация: 11.5.2005
Где: Porto Franco Odes sa

Репутация: 13
Всего: 146



Цитата(Nikfel @  16.7.2009,  19:11 Найти цитируемый пост)
В основном в интернете я натыкался на подобный код через:
Procedure WMDrawItem(var Msg:TWMDrawItem); message wm_DrawItem;
Procedure WMMeasureItem(var Msg:TWMMeasureItem); message wm_MeasureItem;

цикл обработки сообщения есть ?
вот туда и пихаешь 
Код

wm_DrawItem:
begin

end;
wm_MeasureItem:
begin

end;



Добавлено через 2 минуты и 37 секунд
Код

WM_DRAWITEM:
      with PDrawItemStruct(Message.LParam)^ do
      begin
        for I := 0 to Count - 1 do
        begin
          MenuItem := TPopupMenu(Items[I]).FindItem(itemID, fkCommand);
          if MenuItem <> nil then
          begin
            Canvas := TControlCanvas.Create;
            with Canvas do
            try
              SaveIndex := SaveDC(hDC);
              try
                Handle := hDC;
                Font := Screen.MenuFont;
                DrawMenuItem(MenuItem, Canvas, rcItem, TOwnerDrawState(LongRec(itemState).Lo));
              finally
                Handle := 0;
                RestoreDC(hDC, SaveIndex);
              end;
            finally
              Canvas.Free;
            end;
            Exit;
          end;
        end;
      end;
    WM_MEASUREITEM:
      with PMeasureItemStruct(Message.LParam)^ do
      begin
        for I := 0 to Count - 1 do
        begin
          MenuItem := TPopupMenu(Items[I]).FindItem(itemID, fkCommand);
          if MenuItem <> nil then
          begin
            DC := GetWindowDC(Window);
            try
              Canvas := TControlCanvas.Create;
              with Canvas do
              try
                SaveIndex := SaveDC(DC);
                try
                  Handle := DC;
                  Font := Screen.MenuFont;
                  MenuItem.MeasureItem(Canvas, Integer(itemWidth),
                    Integer(itemHeight));
                finally
                  Handle := 0;
                  RestoreDC(DC, SaveIndex);
                end;
              finally
                Canvas.Free;
              end;
            finally
              ReleaseDC(Window, DC);
            end;
            Exit;
          end;
        end;
      end;

вот кусок из TPopupMenu


--------------------
Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. 
smile

PM   Вверх
Nikfel
Дата 16.7.2009, 22:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 15.7.2009
Где: Kirov

Репутация: нет
Всего: нет



Romikgy,  большое спасибо за пример кода, теперь становится понятнее как такое делать. Буду дальше разбираться что к чему.
PM MAIL   Вверх
Nikfel
Дата 19.7.2009, 16:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 15.7.2009
Где: Kirov

Репутация: нет
Всего: нет



Вот еще что мне не понятно:
Как узнать и изменить ширину окна меню?
Как узнать высоту пункта меню и изменить её, т.е. может быть Separator или обычный пункт меню?
PM MAIL   Вверх
Nikfel
  Дата 19.7.2009, 21:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 15.7.2009
Где: Kirov

Репутация: нет
Всего: нет



Разобрался как изменить ширину и высоту пункта меню.
Код

var mii:PMeasureItemStruct;
WM_MeasureItem:begin
    mii:=PMeasureItemStruct(LParam);
    mii.itemWidth:=150;
    mii.itemHeight:=32;
end;


Еще бы как-то узнать что пункт меню это separator и мне надо вывести текст(с заданным шрифтом) и получить ширину и высоту текста. 

Просто если не трудно то напишите какие для этого функции и процедуры нужно использовать?
PM MAIL   Вверх
Romikgy
Дата 20.7.2009, 13:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Любитель-программер
****


Профиль
Группа: Участник Клуба
Сообщений: 7326
Регистрация: 11.5.2005
Где: Porto Franco Odes sa

Репутация: 13
Всего: 146



Цитата(Nikfel @  19.7.2009,  20:48 Найти цитируемый пост)
что пункт меню это separator 

Код

BOOL WINAPI GetMenuItemInfo(

    HMENU hMenu,    
    UINT uItem,    
    BOOL fByPosition,    
    LPMENUITEMINFO lpmii    
   );
typedef struct tagMENUITEMINFO {
    UINT    cbSize;  
    UINT    fMask; 
    UINT    fType; 
    UINT    fState; 
    UINT    wID; 
    HMENU   hSubMenu; 
    HBITMAP hbmpChecked; 
    HBITMAP hbmpUnchecked; 
    DWORD   dwItemData; 
    LPTSTR  dwTypeData; 
    UINT    cch; 
} MENUITEMINFO, FAR *LPMENUITEMINFO; 
 

fType

Menu item type. This member can be one or more of these values:

Value    Meaning
MFT_BITMAP    Displays the menu item using a bitmap. The low-order word of the dwTypeData member is the bitmap handle, and the cch member is ignored.
MFT_MENUBARBREAK    Places the menu item on a new line (for a menu bar) or in a new column (for a drop-down menu, submenu, or shortcut menu). For a drop-down menu, submenu, or shortcut menu, a vertical line separates the new column from the old.
MFT_MENUBREAK    Places the menu item on a new line (for a menu bar) or in a new column (for a drop-down menu, submenu, or shortcut menu). For a drop-down menu, submenu, or shortcut menu, the columns are not separated by a vertical line.
MFT_OWNERDRAW    Assigns responsibility for drawing the menu item to the window that owns the menu. The window receives a WM_MEASUREITEM message before the menu is displayed for the first time, and a WM_DRAWITEM message whenever the appearance of the menu item must be updated. If this value is specified, the dwTypeData member contains an application-defined 32-bit value.
MFT_RADIOCHECK    Displays checked menu items using a radio-button mark instead of a check mark if the hbmpChecked member is NULL.
MFT_RIGHTJUSTIFY    Right-justifies the menu item and any subsequent items. This value is valid only if the menu item is in a menu bar.
MFT_SEPARATOR    Specifies that the menu item is a separator. A menu item separator appears as a horizontal dividing line. The dwTypeData and cch members are ignored. This value is valid only in a drop-down menu, submenu, or shortcut menu.
MFT_STRING    Displays the menu item using a text string. The dwTypeData member is the pointer to a null-terminated string, and the cch member is the length of the string.
 

The MFT_BITMAP, MFT_SEPARATOR, and MFT_STRING values cannot be combined with one another.


Цитата(Nikfel @  19.7.2009,  20:48 Найти цитируемый пост)
мне надо вывести текст(с заданным шрифтом) и получить ширину и высоту текста. 


Цитата(Romikgy @  16.7.2009,  20:08 Найти цитируемый пост)
 DC := GetWindowDC(Window);

+
Код

BOOL GetTextExtentPoint32(

    HDC hdc,    // handle of device context 
    LPCTSTR lpString,    // address of text string 
    int cbString,    // number of characters in string 
    LPSIZE lpSize    // address of structure for string size  
   );




--------------------
Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. 
smile

PM   Вверх
Nikfel
  Дата 20.7.2009, 15:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 15.7.2009
Где: Kirov

Репутация: нет
Всего: нет



Спасибо, буду дальше разбираться. Но вот еще что не ясно:

как закрасить всю область выпадающего меню, а не только перекрасить пункты меню? А вот как получить hdc всего выпадающего меню, а то у меня как-то не красиво получается по бокам белый фон.
PM MAIL   Вверх
Romikgy
Дата 20.7.2009, 20:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Любитель-программер
****


Профиль
Группа: Участник Клуба
Сообщений: 7326
Регистрация: 11.5.2005
Где: Porto Franco Odes sa

Репутация: 13
Всего: 146



http://torry.net/pages.php?id=149
http://torry.net/pages.php?id=147
http://torry.net/pages.php?id=150
качай где FWS , там есть исходники , и разбирай как заменяют отрисовку стандартного меню своим!


--------------------
Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. 
smile

PM   Вверх
Nikfel
Дата 21.7.2009, 11:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 15.7.2009
Где: Kirov

Репутация: нет
Всего: нет



Спасибо, буду разбираться.

А как на счет такого способа рисования по всему меню:

Код

WM_DrawItem:begin
   H0:=FindWindow('#32768',nil);//получаем хандле окна меню
   H1:=getwindowdc(H0);//получаем hdc всего меню
end;

PM MAIL   Вверх
Nikfel
  Дата 22.7.2009, 11:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 15.7.2009
Где: Kirov

Репутация: нет
Всего: нет



Для рисования по всему меню лучше всего делать так:
Код

var dis:PDrawItemStruct;
WM_DRAWITEM:begin
dis:=PDrawItemStruct(LParam);
getwindowdc(WindowFromDC(dis.hDC)); //hdc всего меню
end;

Никак не могу разобраться с GetMenuItemInfo. Почему-то не работает вот это:
Код

function GetMenuIDName(itemID:integer):boolean;
var Buffer: array[0..50] of Char;
begin
MII.cbSize        := SizeOf(MENUITEMINFO);
MII.fMask         := MIIM_STRING or MIIM_TYPE;
MII.fType         := MFT_STRING or MFT_OWNERDRAW;
MII.dwTypeData    := buffer;
MII.cch           := 1023;
result:=false;
If GetMenuItemInfo(Menu,itemID,false,MII) then begin
result:=true;
ItemName:=mii.dwTypeData;
end;
end;


menu:=getsubmenu(getmenu(wnd),0);

Где тут ошибка? функция GetMenuItemInfo всегда возвращает False, а значит не работает.
PM MAIL   Вверх
Romikgy
Дата 22.7.2009, 11:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Любитель-программер
****


Профиль
Группа: Участник Клуба
Сообщений: 7326
Регистрация: 11.5.2005
Где: Porto Franco Odes sa

Репутация: 13
Всего: 146



Цитата(Nikfel @  22.7.2009,  10:35 Найти цитируемый пост)
GetMenuItemInfo всегда возвращает False

обработай ошибку используя GetLastError 
и посмотри что не в поряде


--------------------
Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. 
smile

PM   Вверх
Nikfel
  Дата 28.7.2009, 13:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 15.7.2009
Где: Kirov

Репутация: нет
Всего: нет



Вот решил вот так записать. Где могут быть ошибки? Как лучше записать?  Почему-то ширину получаю не правильно, если submenu. Как исправить?

Код

program menu_;

uses
 Windows, Messages, commctrl;

type
MYITEM = record
  szItemText:String[30];
  ico:Longint;
end;
 var intKD:integer;
 myItem_:array[0..17] of MYITEM;//кол-во пунктов меню, не считая separator
const HeightItem=20;
      HeightItemSeparator=4;
      LeftText=5; //для главного меню смещение текста
      LeftText_=30; //для выпадающего меню смещение текста

procedure SetMenuOwnerDraw(menu1:HMenu);//изменяем стиль для пунктов меню на mf_OwnerDraw, чтобы можно было рисовать
  type TinfoMenu = record
    info:MENUITEMINFO;
    b:boolean;
  end;
var i:integer;
mii:TinfoMenu;
minf:menuiteminfo;
  function GetMenuIDName(Menu_:HMenu; INDEX:integer):TinfoMenu;//получаем информацию о пункте меню
  var Buffer: array[0..30] of Char;
  begin
    result.info.cbSize        := SizeOf(MENUITEMINFO);
    result.info.fMask         := MIIM_FTYPE or miim_submenu or miim_string;
    result.info.dwTypeData    := buffer;
    result.info.cch           := sizeof(buffer);
  If GetMenuItemInfo(Menu_,INDEX,true,result.info) then begin
    result.b:=true;
  end;
  end;
  function getico_(intI_:integer):HICON;//для установки значка для пункта меню
  begin
  Result:=0;
    case intI_ of
      1:Result:=loadicon(hinstance,'MENUNEW');
      2:Result:=loadicon(hinstance,'MENUOPEN');
      4:Result:=loadicon(hinstance,'MENUSAVE');
      9:Result:=loadicon(hinstance,'MENUEXIT');
      11:Result:=loadicon(hinstance,'MENUCUT');
      12:Result:=loadicon(hinstance,'MENUCOPY');
      13:Result:=loadicon(hinstance,'MENUPASTE');
      14:Result:=loadicon(hinstance,'MENUDELETE');
      16:Result:=loadicon(hinstance,'MENUHELP');
    end;
  end;
begin
if menu1<>0 then begin
  for i:=0 to GetMenuItemCount(menu1)-1 do begin//цикл по всем пунктам меню
    mii:=GetMenuIDName(menu1,i);
    if mii.b then begin//если получить информацию о пункте удалось то
      if MII.info.fType=MF_SEPARATOR then begin//если SEPARATOR то так:
        ModifyMenu(menu1,i,mf_OwnerDraw or MF_SEPARATOR or mf_ByPosition,0,nil);
      end else begin
      minf.cbSize:= sizeof(MENUITEMINFO);
      minf.fMask := MIIM_TYPE or MIIM_DATA;
      minf.fType := MFT_OWNERDRAW;
      minf.dwItemData :=intKD;
      myItem_[intKD].szItemText:=MII.info.dwTypeData;
      myItem_[intKD].ico:=getico_(intKD);
      SetMenuItemInfo(menu1,i,true,minf);
      inc(intKD);
      end;
      if MII.info.hSubMenu <>0 then SetMenuOwnerDraw(MII.info.hSubMenu);//если есть выпадающее меню, то снова вызываем процедуру
    end;
  end;
end;
end;

procedure Line(DC_:HDC;x1,y1,x2,y2:integer);
begin
  MoveToEx(DC_,x1,y1,nil);
  LineTo(DC_,x2,y2);
end;

procedure drawmenu(ID,intX,Left_Text:Longint;DC:hdc;Move:boolean;R:TRect);
const Color1:array[0..19] of integer=
($00FAE9D6,$00FAE9D6,$00FAE7CE,$00F8E2C5,$00F5DFBC,
$00F5DFBB,$00F3DBB8,$00F3DBB8,$00F2D9B7,
$00F1D8B3,$00F1D8B1,$00EFD3AA,$00EFD3AA,
$00EED2A6,$00ECD0A1,$00ECD0A1,$00EED2A6,
$00EED3A7,$00F0D4AB,$00F0D4AB);
Color2=$00F3AE7E;
var hMemDC:hDC;
pen,oldPen:Hpen;
Brush,oldBrush:HBRUSH;
hOldBitmap,Bitmap:HBitmap;
i:integer;
myfont,oldfont:hfont;
Height_,WidthItem:integer;
strText:string;
begin
  hMemDC:=CreateCompatibleDC(DC);
  if hMemDC<>0 then begin
    WidthItem:=R.Right-R.Left;
    if ID=0 then strText:='' else strText:=myItem_[intX].szItemText;
    if strText='' then Height_:=HeightItemSeparator else Height_:=HeightItem;
    Bitmap:=CreateCompatibleBitmap(dc,WidthItem,Height_);//создаем изображение на котором будем рисовать
    hOldBitmap:=SelectObject(hMemDC, Bitmap);
    SetBkMode(hMemDC, TRANSPARENT);//задаем прозрачный фон для вывода текста
    SetBkMode(DC, TRANSPARENT);
    myfont := CreateFont(HeightItem-4, 0, 0, 0, FW_NORMAL, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, 'Tahoma');
    oldfont:=SelectObject(hMemDC,myfont);
    Brush:=CreateSolidBrush(rgb(240,240,240));
    oldBrush:=SelectObject(hMemDC,Brush);
    PatBlt(hMemDC,0,0,WidthItem,HeightItem,rgb(240,240,240));
    if Move then begin
      for i:=0 to HeightItem-1 do begin
        //рисуем фон для выделенного пункта меню
        Pen:=CreatePen(PS_SOLID, 1, Color1[i]);
        oldPen:=SelectObject(hMemDC,pen);
        Line(hMemDC,0,i,WidthItem,i);
        SelectObject(hMemDC,oldpen);
        DeleteObject(pen);
      end;
      //рисуем рамку для выделенного пункта меню
      Pen:=CreatePen(PS_SOLID, 1, Color2);
      oldPen:=SelectObject(hMemDC,pen);
      Line(hMemDC,1,0,WidthItem-1,0);
      Line(hMemDC,1,HeightItem-1,WidthItem-1,HeightItem-1);
      Line(hMemDC,0,1,0,HeightItem-1);
      Line(hMemDC,WidthItem-1,1,WidthItem-1,HeightItem-1);
      SelectObject(hMemDC,oldpen);
      DeleteObject(Pen);
    end else begin
      if Left_Text=LeftText_ then begin //если главное меню то не рисуем
        Pen:=CreatePen(PS_SOLID, 1, rgb(224,224,224));
        oldPen:=SelectObject(hMemDC,pen);
        Line(hMemDC,25,0,25,HeightItem);
        SelectObject(hMemDC,oldpen);
        DeleteObject(Pen);
        Pen:=CreatePen(PS_SOLID, 1, rgb(255,255,255));
        oldPen:=SelectObject(hMemDC,pen);
        Line(hMemDC,26,0,26,HeightItem);
        SelectObject(hMemDC,oldpen);
        DeleteObject(Pen);
      end;
    end;
    if strText<>'' then begin
      textout(hMemDC,Left_Text,2,pchar(strText),length(strText));
      //выводим картинку
      if myItem_[intX].ico>0 then DrawIconEx(hMemDC,5,2,myItem_[intX].ico,HeightItem-4,HeightItem-4,0,0,3);
    end else begin
      //если separator то
      Pen:=CreatePen(PS_SOLID, 1, rgb(224,224,224));
      oldPen:=SelectObject(hMemDC,pen);
      Line(hMemDC,27,1,WidthItem-1,1);
      SelectObject(hMemDC,oldpen);
      DeleteObject(Pen);
      Pen:=CreatePen(PS_SOLID, 1, rgb(255,255,255));
      oldPen:=SelectObject(hMemDC,pen);
      Line(hMemDC,27,2,WidthItem-1,2);
      SelectObject(hMemDC,oldpen);
      DeleteObject(Pen);
    end;
    BitBlt(DC, r.Left, r.Top, WidthItem, HeightItem, hMemDC, 0, 0, SRCCOPY);
    SelectObject(hMemDC,oldfont);
    SelectObject(hMemDC,oldBrush);
    DeleteObject(myfont);
    DeleteObject(Brush);
    SelectObject(hMemDC, hOldBitmap);
    DeleteObject(Bitmap);
    DeleteDC(hMemDC);
  end;
end;

function GetTextWidth(wnd_:hwnd;strS:string):integer;//получаем ширину текста
var DC_:HDC;
myfont,oldfont:HFont;
siz:Size;
begin
DC_:=GetDC(wnd_);
myfont := CreateFont(HeightItem-4, 0, 0, 0, FW_NORMAL, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, 'Tahoma');
oldfont:=SelectObject(DC_,myfont);
GetTextExtentPoint32(DC_,pchar(strS),length(strS),siz);
result:=siz.cx;
SelectObject(DC_,oldfont);
DeleteObject(myfont);
ReleaseDC(wnd_,DC_);
end;

procedure drawMenuWnd(DC:HDC);
var h:hwnd;
pen,oldPen:Hpen;
DC_:hdc;
t:trect;
begin
h:=WindowFromDC(DC);
DC_:=GetWindowDC(h);
GetClientRect(h,t);
Pen:=CreatePen(PS_SOLID, 1, rgb(127,157,185));
oldPen:=SelectObject(DC_,pen);
Line(DC_,0,0,t.Right+6,0);
Line(DC_,0,0,0,t.Bottom+6);
Line(DC_,t.Right+5,0,t.Right+5,t.Bottom+6);
Line(DC_,0,t.Bottom+5,t.Right+5,t.Bottom+5);
SelectObject(DC_,oldpen);
DeleteObject(Pen);
ReleaseDC(h,DC_);
end;

function DlgProc(hWin, uMsg, wParam, lParam: Integer): Integer; stdcall;
var t:tpoint;
DIS:PDRAWITEMSTRUCT;
mis:PMeasureItemStruct;
begin
 Result := 0;
  case uMsg of
   WM_INITDIALOG:
    begin
     intKD:=0;
     SendMessage(hWin, WM_SETICON, ICON_BIG, LoadIcon(hInstance, 'MAINICON'));
     SetMenu(hwin,LoadMenu(HInstance, 'MAINMENU'));
     SetMenuOwnerDraw(GetMenu(hwin));
    end;
   WM_MeasureItem:begin
    mis:=PMeasureItemStruct(LParam);
    if mis.CtlType=ODT_MENU then begin
      mis.itemHeight:=HeightItem;
      if mis.itemID=0 then mis.itemHeight:=HeightItemSeparator;
      mis.itemWidth:=GetTextWidth(hwin,myItem_[mis.itemData].szItemText)+20;
      if MIS.itemID>10000 then mis.itemWidth:=GetTextWidth(hwin,myItem_[mis.itemData].szItemText);//если заголовок главного меню
    end;
     end;
   WM_DrawItem:begin
    DIS := PDrawItemStruct(LParam);
    if integer(WindowFromDC(dis.hDC))<>hwin then drawMenuWnd(dis.hDC);//рисуем по всему окну меню
    if DIS.itemState=257 then begin
      //при помещении курсора мыши над элементом меню или при нажатом пункте главного меню
        if dis.hwndItem=getmenu(hwin) then drawmenu(dis.itemID,dis.itemData,LeftText,dis.hDC,true,dis.rcItem) else
          drawmenu(dis.itemID,dis.itemData,LeftText_,dis.hDC,true,dis.rcItem);
    end else begin
      //при помещении курсора мыши над элементом главного меню и при нажатии кнопки Alt
        if (DIS.itemState=320) or (DIS.itemState=1) then begin
          if dis.hwndItem=getmenu(hwin) then drawmenu(dis.itemID,dis.itemData,LeftText,dis.hDC,true,dis.rcItem) else
            drawmenu(dis.itemID,dis.itemData,LeftText_,dis.hDC,true,dis.rcItem);
        end else begin
      //когда курсор мыши уходит с пункта меню
          if dis.hwndItem=getmenu(hwin) then drawmenu(dis.itemID,dis.itemData,LeftText,dis.hDC,false,dis.rcItem) else  //5
            drawmenu(dis.itemID,dis.itemData,LeftText_,dis.hDC,false,dis.rcItem);
        end;
    end;
   end;
   WM_COMMAND:
    begin
     case LoWord(wParam) of
      1001,1002: EndDialog(hWin, 0);
      1003:begin
      //вызов popup меню
      GetCursorPos(t);
      TrackPopupMenuEx(getsubmenu(getmenu(hwin),1),0,t.X,t.Y,hwin,nil);
      end;
    end;
  end;
   WM_DESTROY, WM_CLOSE: begin
   PostQuitMessage(0);
   end;
 end;
end;

begin
{$R WindowsXP.res}
{$R menu.res}
 InitCommonControls;
 DialogBox(hInstance, 'MAIN_WINDOW', 0, @DlgProc);
end.



Присоединённый файл ( Кол-во скачиваний: 7 )
Присоединённый файл  menu_.RAR 20,20 Kb
PM MAIL   Вверх
Nikfel
Дата 29.7.2009, 15:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 15.7.2009
Где: Kirov

Репутация: нет
Всего: нет



Вот исправленный вариант меню, но только странно то что если задаешь массив
Код

myItem_:array[0..0] of MYITEM;

то это не вызывает ошибку. Возможно могут быть утечки памяти или из-за чего такое происходит не пойму, т.к. у меня может быть такое myItem_[25].

Это сообщение отредактировал(а) Nikfel - 29.7.2009, 15:03

Присоединённый файл ( Кол-во скачиваний: 9 )
Присоединённый файл  menu_.RAR 20,46 Kb
PM MAIL   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: WinAPI и системное программирование"
Snowybartram
MetalFanbems
PoseidonRrader
Riply

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Delphi обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи
  • 99% ответов по WinAPI можно найти в MSDN Library, оставшиеся 1% здесь

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, bartram, MetalFan, bems, Poseidon, Rrader, Riply.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: WinAPI и системное программирование | Следующая тема »


 




[ Время генерации скрипта: 0.0825 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.