Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.116.40.47] |
|
Сообщ.
#1
,
|
|
|
Delphi XE2.
Для формы делаю: hFont := SendMessage(Self.Handle, WM_GETFONT, 0, 0); Но возвращает 0. Т.е. как будто у формы установлен системный шрифт. Почему так? А если сделать, например, так: hFont := SendMessage(CheckBox1.Handle, WM_GETFONT, 0, 0); То возвращает корректный дескриптор. Тоже самое, например, для TPanel - hFont = 0. А для кнопки hFont - корректное значение. |
Сообщ.
#2
,
|
|
|
Вроде бы потому, что там у них формы/панели создаётся как некое виртуальное окно (точнее, ненастоящее виндовое) и потому такие особенности.
|
Сообщ.
#3
,
|
|
|
Цитата Славян @ Вроде бы потому, что там у них формы/панели создаётся как некое виртуальное окно (точнее, ненастоящее виндовое) и потому такие особенности. Но свойство Handle возвращает корректное значение. Т.е. некое WinApi-окно все-таки есть. |
Сообщ.
#4
,
|
|
|
Да, некое, но не из списка стандартных виндовых, и не их потомок.
|
Сообщ.
#5
,
|
|
|
Цитата Славян @ Да, некое, но не из списка стандартных виндовых, и не их потомок. Не, это именно стандартый Win32-дескриптор. Вот этот код: .............. .............. GetWindowInfo('Form', Self.Handle); GetWindowInfo('Panel2', Panel2.Handle); GetWindowInfo('Button3', Button3.Handle); GetWindowInfo('Edit1', Edit1.Handle); GetWindowInfo('StaticText1', StaticText1.Handle); .............. .............. procedure TMainForm.GetWindowInfo(AName: String; AHandle: HWND); var hFont: Winapi.Windows.HFONT; R: TRect; ProcessId, ThreadId: DWORD; hParentWnd: Winapi.Windows.HWND; FileName: array[0..2000] of Char; begin Memo1.Lines.Add(''); hFont := Winapi.Windows.HFONT(SendMessage(AHandle, WM_GETFONT, 0, 0)); Memo1.Lines.Add('Name: ' + AName); Memo1.Lines.Add('Handle: ' + IntToHex(AHandle, 8)); Memo1.Lines.Add('Font Handle: ' + IntToHex(hFont, 8)); R := Rect(-1, -1, -1, -1); GetWindowRect(AHandle, R); Memo1.Lines.Add('WindowRect: ' + IntToStr(R.Left) + ', ' + IntToStr(R.Top) + ', ' + IntToStr(R.Right) + ', ' + IntToStr(R.Bottom)); ThreadId := GetWindowThreadProcessId(AHandle, ProcessId); Memo1.Lines.Add('ProcessId: ' + UIntToStr(ProcessId) + ', ThreadId: ' + UIntToStr(ThreadId)); hParentWnd := GetParent(AHandle); Memo1.Lines.Add('Parent Handle: ' + IntToHex(hParentWnd, 8)); FillChar(FileName, SizeOf(FileName), 0); GetWindowModuleFileName(AHandle, @FileName, 2000); Memo1.Lines.Add('Module File Name: ' + FileName); end; Выдает это: Цитата Name: Form Handle: 00370964 Font Handle: 00000000 WindowRect: 92, 56, 916, 802 ProcessId: 1688, ThreadId: 5864 Parent Handle: 00000000 Module File Name: D:\temp\proba1.exe Name: Panel2 Handle: 0025086A Font Handle: 00000000 WindowRect: 460, 371, 645, 412 ProcessId: 1688, ThreadId: 5864 Parent Handle: 00370964 Module File Name: D:\temp\proba1.exe Name: Button3 Handle: 002B0862 Font Handle: 360A11BB WindowRect: 468, 267, 543, 292 ProcessId: 1688, ThreadId: 5864 Parent Handle: 00370964 Module File Name: D:\temp\proba1.exe Name: Edit1 Handle: 00240818 Font Handle: 360A11BB WindowRect: 460, 344, 581, 365 ProcessId: 1688, ThreadId: 5864 Parent Handle: 00370964 Module File Name: D:\temp\proba1.exe Name: StaticText1 Handle: 00210D6A Font Handle: 360A11BB WindowRect: 539, 321, 598, 338 ProcessId: 1688, ThreadId: 5864 Parent Handle: 00370964 Module File Name: D:\temp\proba1.exe |
Сообщ.
#6
,
|
|
|
Цитата wb4 @ Но возвращает 0. Т.е. как будто у формы установлен системный шрифт. Ну всё правильно: Цитата WM_GETFONT: The return value is a handle to the font used by the control, or NULL if the control is using the system font. А что именно смущает? Система по дефолту задаёт окну системный шрифт через GetStockObject(DEFAULT_GUI_FONT). Это тот шрифт, которым отображаются меню, текст, и т.д. В Delphi окну (форме) фонт задаёт система именно так (только если ты сам явно не задашь для окна какой-то другой шрифт). По этому WM_GETFONT у тебя и возвращает 0. Цитата wb4 @ Т.е. некое WinApi-окно все-таки есть. Любое окно в Windows создаётся одинаково - регистрируется класс окна и вызывается CreateWindow. Ну а все эти т.н. "виртуальные" окна - просто прорисовка на экране (например TLabel - рисование текста ф-ей DrawText(Ex)). |
Сообщ.
#7
,
|
|
|
Цитата Krid @ А что именно смущает? Система по дефолту задаёт окну системный шрифт через GetStockObject(DEFAULT_GUI_FONT). Это тот шрифт, которым отображаются меню, текст, и т.д. В Delphi окну (форме) фонт задаёт система именно так (только если ты сам явно не задашь для окна какой-то другой шрифт). По этому WM_GETFONT у тебя и возвращает 0. Смущает то, что в отладчике четко видно, что для каждого компонента производится вызов: procedure TWinControl.CreateWnd; begin ........... ........... Perform(WM_SETFONT, FFont.Handle, 1); ........... ........... end; Для всех компонент одинаково. И TPanel рисует свой Caption своим "родным" шрифтом, но не системным. |
Сообщ.
#8
,
|
|
|
А что у тебя возвращает
SendMessage(Panel1.Handle, WM_GETFONT, 0, 0); У меня - ноль. Т.е. TPanel рисует свой Caption системным шрифтом. |
Сообщ.
#9
,
|
|
|
Цитата Krid @ Т.е. TPanel рисует свой Caption системным шрифтом. Хорошо. Я поставил форме шрифт "Monotype Corsiva" размером 12. Т.е. даже близко не системный. Ситуация осталась та же - форма и панель сообщают, что у них типа системный шрифт (дескриптор шрифта = 0) |
Сообщ.
#10
,
|
|
|
Ну тогда конкретизируй, плз. - ты хочешь: поменять шрифт формы, не затрагивая шрифт контролов на ней. Или ты хочешь поменять шрифт формы так, чтобы шрифт контролов тоже поменялся (например, шрифт панели). Или у тебя чисто академический интерес - как можно поменять шрифт формы, чтобы он не был системным и WM_GETFONT для формы не выдавал ноль?
Что именно тебе нужно? ЗЫ да, и обрати внимание на ф-ю TWinControl.RecreateWnd, - которая уничтожает Canvas (он же hDC, на котором всё и рисуется - и Font тоже, т.к. юзает hDC), а потом создаёт его снова - т.е. hDC и hFont сначала уничтожаются а потом сразу создаются с другими значениями hDC и hFont, чтобы потом можно рисовать на canvas (hDC), юзая заданный фонт. Короче, для начала внимательно прочти матчасть. |
Сообщ.
#11
,
|
|
|
Сообщ.
#12
,
|
|
|
Цитата Krid @ Ну тогда конкретизируй, плз. - ты хочешь... ........ Мне нужно получить шрифт контрола для различных вычислений, связанных с размерами и кастомным выравниванием. Желательно иметь универсальный доступ к контролу - через одну переменную, которая представляет TControl/TWinControl или дескриптор окна. Добавлено Цитата MBo @ А вот это интересно! Спасибо! |
Сообщ.
#13
,
|
|
|
Формы в Delphi создаются по правилам, по которым создаются все окна в винде, и это ты стандартными способами не изменишь.
Для отдельных контролов сделать это можно, но для этого нужно перехватить процедуру создание контрола. Шрифт каких именно контролов ты хочешь поменять? |
Сообщ.
#14
,
|
|
|
wb4
type THackControl = class(TControl); //... procedure TForm1.Button1Click(Sender: TObject); procedure MyProc(AControl: TControl); begin ShowMessage(THackControl(AControl).Font.Name); //THackControl(AControl).Font.Size := 12; end; begin MyProc(Form1); MyProc(Panel1); MyProc(CheckBox1); MyProc(Button1); end; //... |
Сообщ.
#15
,
|
|
|
не сработает
|
Сообщ.
#16
,
|
|
|
Ну вот так сработает:
class TMyCntrl : public TControl { public: TMyCntrl(TComponent *a, int) : TControl(a) {} // фикция long MyOffset() // смещение, где FFont; { char *ono = (char*)this->Font; char *fini = &((char*)this)[sizeof(TControl)-2*sizeof(TFont*)]; for( int t=0; t<sizeof(TFont*); t++) for( TFont **f=(TFont**)(t+(char*)this); f<fini; f++) if( *f==ono ) return (long)f - (long)this; // поиск адреса return 0; // не нашли } }; void MyProc(TControl *AControl) { TMyCntrl *a = new TMyCntrl(AControl,0); long o = a->MyOffset(); // смещение, где FFont; if( !o ) return; TFont *f = *(TFont **)&(((char*)AControl)[o]); ShowMessage(f->Name); } void __fastcall TForm1::Button1Click(TObject *Sender) { MyProc(this); MyProc(Button1); MyProc(Panel1); Caption = this->Font->Name + Panel1->Font->Name + Button1->Font->Name; ... П.С. да и надёжность низкая, и куча других недостатков. |
Сообщ.
#17
,
|
|
|
Да и вообще это C++Builder , так что руки отрывать надо однозначно
|
Сообщ.
#18
,
|
|
|
Цитата Krid @ не сработает Это ты про THackControl? Почему не сработает? Должно работать для всех контролов и форм, наследующих стандартное хранение\изменение свойств Font и ParentFont от TControl. |
Сообщ.
#19
,
|
|
|
Цитата leo @ Это ты про THackControl? Почему не сработает? WM_GETFONT всё равно ноль возвращает (не смотря на Form1.ParentFont) |
Сообщ.
#20
,
|
|
|
Цитата Krid @ WM_GETFONT всё равно ноль возвращает (не смотря на Form1.ParentFont) Причем тут WM_GETFONT? MBo же привел ссылки, да и в мсдн черным по белому сказано, что WM_GETFONT работает для контролов (читай - стандартных виндовых), а не для любых окон. Для форм\диалогов и самопальных контролов нужно самому задавать обработчик сообщения WM_GETFONT. Но в VCL этого не сделано, т.к. для любого наследника TControl можно получить всю инфу о шрифте проще - через св-во Font. Вот THackControl и обеспечивает доступ к Font для любого наследника TControl. А если нужно добраться до этого св-ва через дескриптор окна, то для VCL-окон можно использовать функцию FindControl |