-
Я пишу проект на WinAPI и GDI, и допустим, хочу написать Dll, из которой экспортирую функцию, которая вызывает контекстное меню. Однако, само меню я решил также написать как окно на WinAPI, т.к. для этого меню у меня есть собственный дизайн, с нарисованным фоном и кнопками. Внутри функции в Dll'ке я создаю и регистрирую класс окна, создаю собственно окно меню, там же находится процедура-обработчик сообщений окна. Однако, если после создания окна прописать цикл обработки сообщений TranslateMessage-DispatchMessage, то само собой, сама процедура создания контекстного меню "повесит" все приложение, пока меню не будет уничтожено. Собственно, вопрос в том, как в одном приложении использовать и обрабатывать несколько окон на WinAPI?
-
У тебя этот цикл в основной программе уже есть, он один для всех окон потока. Отдельный цикл нужно создавать для отдельного потока. Для каждого окна создавать отдельный цикл не нужно.
P.S. если не сложно скинь пример менюшки на winapi мне на почту reg argi ru.
-
> если после создания окна прописать цикл обработки сообщений > TranslateMessage-DispatchMessage, то само собой, сама процедура > создания контекстного меню "повесит" все приложение, пока > меню не будет уничтожено
Это с какого же перепугу "повесит" ?
-
Собственно проблема в том, что при вызове меню ничего не происходит: функция вызывается корректно, но никаких следов появления меню, даже малейшей задержки в работе программы при загрузке изображений не происходит. Само меню пока очень сырое, и написано до момента, когда его можно подключить к проекту и тестировать. В нем не до конца прописано уничтожение окна и не прописана реакция на кнопки. Собственно, задумка такова: Из Dll экспортируется ф-я ,которой передается хендл окна его вызывающего, передается адрес процедуры обратного вызова, которая будет обрабатывать события на кнопках из основного кода проекта, также передаются координаты курсора. Код оочень сырой, но выложу тут чтобы узнать, где именно кроется загвоздка.
library Menu;
uses
Windows,
SysUtils,
Classes,
messages;
type
TRe_Action = (A_Exit, A_Hide, A_Show, A_SoundOn, A_SoundOff);
TRe_Menu_proc = procedure (Action: TRe_Action; Param: Integer);
PRe_Menu_proc = ^TRe_Menu_proc;
Var
Message: TMsg;
function ScreenWidth: integer;
begin
result:=GetSystemMetrics(SM_CXVIRTUALSCREEN);
end;
function ScreenHeight: integer;
begin
result:=GetSystemMetrics(SM_CYVIRTUALSCREEN);
end;
function Create_Menu(Handle: HWND; Menu_proc: PRe_Menu_proc; X, Y: integer): HWND; stdcall;
var
wc : TWndClassEx; xPos,yPos,nWidth,nHeight : Integer;
TRgn, FoneRgn: HRGN;
Dc,hMemDc: Hdc;
PIC_Exit1, PIC_Exit2, PIC_Exit3, PIC_Fone, PIC_Hide1, PIC_Hide2, PIC_Hide3,
PIC_Show1, PIC_Show2, PIC_Show3, PIC_Soff1, PIC_Soff2, PIC_Soff3, PIC_Son1,
PIC_Son2, PIC_Son3: HBitmap;
function BitmapToRgn(PosX, PosY, width, height: integer; Image: HBitmap): HRGN;
var
TmpRgn: HRGN;
x, y: Byte;
ConsecutivePixels: integer;
CurrentPixel: COLORREF;
CurrentColor: COLORREF;
TmpDC: HDC;
begin
Result := CreateRectRgn(0, 0, PosX+width-1, PosY+height-1);
TmpDC:= CreateCompatibleDC(Dc);
SelectObject(TmpDC,Image);
for y := 0 to height-1 - 1 do
begin
CurrentColor := GetPixel(TmpDC,0,y);
ConsecutivePixels := 1;
for x := 0 to width-1 - 1 do
begin
CurrentPixel := GetPixel(TmpDC,x,y);
if CurrentColor = CurrentPixel then
inc(ConsecutivePixels)
else
begin if (CurrentColor = $ff00ff) or (CurrentColor = $00C8C4C8) then
begin
TmpRgn := CreateRectRgn(PosX+x-ConsecutivePixels, PosY+y, PosX+x, PosY+y+1);
CombineRgn(Result, Result, TmpRgn, RGN_DIFF);
DeleteObject(TmpRgn);
end;
CurrentColor := CurrentPixel;
ConsecutivePixels := 1;
end;
end;
if ((CurrentColor = $ff00ff) or (CurrentColor = $00C8C4C8)) and (ConsecutivePixels > 0) then
begin
TmpRgn := CreateRectRgn(PosX+x-ConsecutivePixels, PosY+y, PosX+x, PosY+y+1);
CombineRgn(Result, Result, TmpRgn, RGN_DIFF);
DeleteObject(TmpRgn);
end;
end;
DeleteDC(TmpDC);
end;
function WindowProc(wnd:HWND; Msg : Integer; Wparam:Wparam; Lparam:Lparam):Lresult; stdcall;
Begin
case msg of
wm_create :
Begin
DC := GetWindowDC(wnd);
PIC_Exit1 := LoadBitmap(hInstance, 'RE_M_EXIT1');
PIC_Exit2 := LoadBitmap(hInstance, 'RE_M_EXIT2');
PIC_Exit3 := LoadBitmap(hInstance, 'RE_M_EXIT3');
PIC_Fone := LoadBitmap(hInstance, 'RE_M_FONE');
PIC_Hide1 := LoadBitmap(hInstance, 'RE_M_HIDE1');
PIC_Hide2 := LoadBitmap(hInstance, 'RE_M_HIDE2');
PIC_Hide3 := LoadBitmap(hInstance, 'RE_M_HIDE3');
PIC_Show1 := LoadBitmap(hInstance, 'RE_M_SHOW1');
PIC_Show2 := LoadBitmap(hInstance, 'RE_M_SHOW2');
PIC_Show3 := LoadBitmap(hInstance, 'RE_M_SHOW3');
PIC_Soff1 := LoadBitmap(hInstance, 'RE_M_SOFF1');
PIC_Soff2 := LoadBitmap(hInstance, 'RE_M_SOFF2');
PIC_Soff3 := LoadBitmap(hInstance, 'RE_M_SOFF3');
PIC_Son1 := LoadBitmap(hInstance, 'RE_M_SON1');
PIC_Son2 := LoadBitmap(hInstance, 'RE_M_SON2');
PIC_Son3 := LoadBitmap(hInstance, 'RE_M_SON3');
FoneRgn := BitmapToRgn(0, 0, 129, 97, PIC_Fone);
TRgn:= CreateRectRgn(0,0,1,1);
CombineRgn(TRgn,FoneRgn,Trgn,RGN_COPY);
SetWindowRgn(Wnd,Trgn,True);
WindowProc:= DefWindowProc (wnd, Msg, WParam, LParam);
End;
wm_paint :
Begin
hMemDc := CreateCompatibleDC(dc);
SelectObject(hMemDC,PIC_Fone);
BitBlt(dc, 0, 0, 129, 97, hMemDC, 0, 0, SRCCOPY);
DeleteDC(hMemDC);
WindowProc:= DefWindowProc (wnd, Msg, WParam, LParam);
End;
wm_destroy : Begin
ReleaseDC(Wnd, Dc);
Result:=0;
postquitmessage(0); exit;
WindowProc:= DefWindowProc (wnd, Msg, WParam, LParam);
End
else Result:=DefWindowProc(wnd,msg,wparam,lparam);
end;
End;
begin
result:=0;
wc.cbSize:=sizeof(wc);
wc.style:=cs_hredraw or cs_vredraw;
wc.lpfnWndProc:=@WindowProc;
wc.cbClsExtra:=0;
wc.cbWndExtra:=0;
wc.hInstance:=HInstance;
wc.hIcon:=LoadIcon(0,idi_application);
wc.hCursor:=LoadCursor(0,idc_arrow);
wc.hbrBackground:=COLOR_BTNFACE+1;
wc.lpszMenuName:=nil;
wc.lpszClassName:='TRE_Menu';
RegisterClassEx(wc);
nWidth:=129;
nHeight:=97;
if ScreenWidth-X>=nWidth then
xPos:=x else xPos:=x-nWidth;
if ScreenHeight-Y>=nHeight then
yPos:=y else yPos:=y-nHeight;
result:=CreateWindowEx (
0, //флаги расширенных стилей
'TRE_Menu', //имя класса окна, данное при заполнении структуры wc
'RE_Menu', //заголовок окна
ws_overlappedwindow+WS_VISIBLE, //флаги стилей окна
xPos, //горизонтальная позиция окна
yPos, //вертикальная позиция окна
nWidth, //ширина окна
nHeight, //высота окна
Handle, //описатель родительского окна (parent) или окна-владельца (owner)
0, //описатель меню окна (меню нет, нет и описателя)
Hinstance, //описатель приложения
nil //address of window-creation data
);
ShowWindow(result, SW_SHOW); //Отображаем окно
UpdateWindow (Result);
end;
exports
Create_Menu index 1 name 'Create_Menu';
begin
end.
-
круто... WindowProc - локальная функция ссылающаяся на локальные переменные внешней функции... 1. Delphi7 не поддерживает замыканий... 2. Прежде чем сношать мозги(и себе, и занятым людям) с DLL - убедись что работает "линейный" код в монолитном проекте...
-
Все переменные, необходимые для создания и работы окна прописаны внутри функции. Естественно, не описывать же мне все переменные как глобальные!
-
Где ты увидел замыкания в коде? Выразись пояснее, а то из твоих абстрактно-непонятных, но якобы очевидных обьяснений ничего непонятно.
-
DagOT-R © (13.04.10 17:03) [5]
Тебе явно указали, что оконная процедура не может быть вложенной. Что ты препираешься ?
-
Ок, ясно, спасибо, попробую исправить.
-
И правда, все работает и рисуется отлично. Еще раз спасибо за помощь.
-
А разве такое компилируется для локальной WindowProc: wc.lpfnWndProc:=@WindowProc; ?
-
|