Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "WinAPI";
Текущий архив: 2011.07.10;
Скачать: [xml.tar.bz2];

Вниз

Как перекрасить меню полностью   Найти похожие ветки 

 
Nikfel   (2009-07-26 19:18) [0]

Подскажите, пожалуйста. Никак не могу разобраться как на чистом WinApi сделать меню с прорисовкой своих пунктов. Меню у меня лежит в файле ресурсов. Загружаю его и делаю стиль OwnerDraw для всех пунктов. Проблема в том как правильно обработать сообщения WM_MeasureItem и WM_DrawItem.

[code]
Var mis:PMeasureItemStruct;
DIS:PDrawItemStruct;
WM_MeasureItem:begin
mis:=PMeasureItemStruct(LParam);
//проблема как тут узнать что это главное меню и надо задать для каждого пункта меню ширину
//знаю что это делает mis.itemWidth, но как узнать сам пункт меню? Можно ли тут получить    
//hmenu, зная которое можно пробежаться по всем пунктам меню?
end;
WM_DrawItem:begin
DIS := PDrawItemStruct(LParam);
//тут проблема в том как получить текст пункта меню, через GetMenuItemInfo получить можно, но
//если стиль OwnerDraw, то тогда нельзя.
end;[/code]

Может быть кто-нибудь писал такое на чистом WinApi на Delphi без VCL? Если можно то хотелось бы посмотреть пример? Я пытался сам написать код, но получилось совсем плохо, много проблем. Заранее спасибо.


 
clickmaker ©   (2009-07-27 11:46) [1]

> тут проблема в том как получить текст пункта меню, через
> GetMenuItemInfo получить можно, но
> //если стиль OwnerDraw, то тогда нельзя.

itemData
туда можно положить все, что угодно, см. InsertMenu()


 
Nikfel   (2009-07-27 12:09) [2]

Спасибо. Попробую. Значит можно использовать SetMenuItemInfo для записи туда нужного значения?


 
Nikfel   (2009-07-27 13:37) [3]

typedef struct tagMYITEM {
HFONT hfont;
int cchItemText;
char szItemText[1];
} MYITEM;


type
PMYITEM = ^MYITEM;
MYITEM = record
 hfont: HFONT;
 cchItemText: integer;
 szItemText:Char;
end;


Правильно ли перевел на Delphi c языка C++?

Как перевести на Delphi вот это:

MYITEM *pMyItem;

pMyItem = (MYITEM *) LocalAlloc(LMEM_FIXED,
sizeof(MYITEM) + CCH_MAXITEMTEXT);
pMyItem->cchItemText = mii.cch;
// Перераспределим память для структуры для
 // минимально требуемого размера.
pMyItem = (MYITEM *) LocalReAlloc(pMyItem,
sizeof(MYITEM) + mii.cch, LMEM_MOVEABLE);
pMyItem->hfont = CreateMenuItemFont(uID);
mii.dwItemData = (DWORD) pMyItem;


Взято с http://netcode.ru/cpp/?lang=&katID=8&skatID=93&artID=3634


 
clickmaker ©   (2009-07-27 14:03) [4]

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


 
Nikfel   (2009-07-28 14:13) [5]

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;


 
Nikfel   (2009-07-28 14:14) [6]

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.


 
Nikfel   (2009-07-28 14:15) [7]

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


 
Nikfel   (2009-07-29 16:12) [8]

Вот исправленный вариант меню:
program menu_;

uses
Windows, Messages, commctrl;

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

procedure SetMenuOwnerDraw(menu1:HMenu; wnd:hwnd);//изменяем стиль для пунктов меню на 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);
     if getmenu(wnd)=menu1 then myItem_[intKD].b:=true else myItem_[intKD].b:=false;
     SetMenuItemInfo(menu1,i,true,minf);
     inc(intKD);
     end;
     if MII.info.hSubMenu <>0 then SetMenuOwnerDraw(MII.info.hSubMenu,wnd);//если есть выпадающее меню, то снова вызываем процедуру
   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,16,16,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;


 
Nikfel   (2009-07-29 16:13) [9]

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;
const LeftSub=15;
     LeftMenu=20;
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),hwin);
   end;
  WM_MeasureItem:begin
   mis:=PMeasureItemStruct(LParam);
   if mis.CtlType=ODT_MENU then begin
     if MIS.itemID>10000 then begin
       if myItem_[mis.itemData].b then mis.itemWidth:=GetTextWidth(hwin,myItem_[mis.itemData].szItemText) else //если заголовок главного меню
         mis.itemWidth:=GetTextWidth(hwin,myItem_[mis.itemData].szItemText)+LeftMenu+LeftSub;//если submenu
       mis.itemHeight:=HeightItem;
     end else begin
       mis.itemWidth:=GetTextWidth(hwin,myItem_[mis.itemData].szItemText)+LeftMenu;
       if mis.itemID=0 then mis.itemHeight:=HeightItemSeparator else mis.itemHeight:=HeightItem;
     end;
   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
         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.


 
Nikfel   (2009-07-29 16:15) [10]

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


 
app ©   (2009-07-29 16:28) [11]

> Nikfel  (29.07.2009 16:15:10)  [10]

Хватит портянки постить.


 
Nikfel   (2009-07-29 16:33) [12]

Так я больше и не собирался ничего сюда писать, но только осталось не понятно только одно: почему myItem_:array[0..0] of MYITEM; не вызывает ошибку?


 
clickmaker ©   (2009-07-29 18:22) [13]

> почему myItem_:array[0..0] of MYITEM; не вызывает ошибку?

везет. При другой фазе Луны может не повезти



Страницы: 1 вся ветка

Форум: "WinAPI";
Текущий архив: 2011.07.10;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.53 MB
Время: 0.003 c
15-1300809539
rxQ
2011-03-22 18:58
2011.07.10
ПО под GPL и платные компоненты


15-1300948857
brother
2011-03-24 09:40
2011.07.10
Эмулировать поведение курсора


11-1235124028
BMouradov
2009-02-20 13:00
2011.07.10
Вопрос по PStrListEx


15-1300947070
OW
2011-03-24 09:11
2011.07.10
Как бы Вы написали и почему?


9-1189378302
max_
2007-09-10 02:51
2011.07.10
текстура





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский