Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2011.07.10;
Скачать: CL | DM;

Вниз

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

 
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 вся ветка

Текущий архив: 2011.07.10;
Скачать: CL | DM;

Наверх




Память: 0.55 MB
Время: 0.011 c
15-1300915800
Юрий
2011-03-24 00:30
2011.07.10
С днем рождения ! 24 марта 2011 четверг


3-1261385211
Rhododendrom
2009-12-21 11:46
2011.07.10
BackUp/Restore базы данных FireBird из моей программы.


15-1301002199
Юрий
2011-03-25 00:29
2011.07.10
С днем рождения ! 25 марта 2011 пятница


15-1301334387
Pavia
2011-03-28 21:46
2011.07.10
Посоветуйте компонент


4-1248621510
Nikfel
2009-07-26 19:18
2011.07.10
Как перекрасить меню полностью