WindowsFont
Сообщений 1 страница 13 из 13
Поделиться205.03.2022 00:51:33
Обнолвение
Изменение размера и названия шрифта в имёнах файлов и папок в эксплорере применяется мгновенно, остальное требует выход/вход пользователя.
Поддерживается изменение размера окна.
В каком то смысле это позволяет подбирать размер шрифта. И во вторых лично мне в 90% интересен именно размер шрифта в проводнике, поэтому если бы у меня было много открытых программ и я не хотел бы их закрывать, мне хватило бы изменить размер в проводнике, а остальные вещи я бы мог позже поменять, то есть потерпел бы.
Если у кого есть идеи поменять в реальном времени и другие шрифты, то сообщите.
Поменять размер шрифта заголовка у меня не получилось, хотя это тоже меняет шрифт значков, а не заголовка, точнее вывод size меняется если я в проге меняю шрифт значков.
EnableExplicit Define size, spinfo.LOGFONT SystemParametersInfo_(#SPI_GETICONTITLELOGFONT, 0, @spinfo, 0) size = PeekL(@spinfo\lfHeight) PokeL(@spinfo\lfHeight, size+2) SystemParametersInfo_(#SPI_SETICONTITLELOGFONT, 0, @spinfo, 0)
Отредактировано AZJIO (05.03.2022 13:03:38)
Поделиться305.03.2022 06:39:31
SystemParametersInfo_(#SPI_SET...., 0, @spinfo, 0)
попытался этим воспользоваться, всё накрылось медным тазом, после перезагрузки само всё восстановилось
надо думать что то неправильно я делал
пока бросил эту затею
lfHeight = -MulDiv(PointSize, GetDeviceCaps(hDC, #LOGPIXELSY), 72)
код возвращает размер шрифта который мы видим в редакторах при выборе шрифта
Поделиться405.03.2022 13:00:39
Итак, методом тыка и гуглингом выяснил следующее:
1. Функция MulDiv() тут
2. Число 72 и PointSize подтолкнуло на мысль, что числа 12 и -16 связаны меж собой вычислением DPI мне осталось поиграть числами в функции моим DPI, размером шрифта 12 и вычисляемым -16, который в реестре и в Firefox.
Debug -MulDiv(96, 12, 72)
Понятно что теперь я должен для этой проги запросить DPI и найти обратную функцию, получение 12 из -16. Помню что SystemParametersInfo запрашивает DPI, есть у ней параметр для возврата DPI.
Примерно так
Define hDC, DPI, PointSizeб lfHeight hDC = GetWindowDC_(0) DPI = GetDeviceCaps_(hDC, #LOGPIXELSY) ReleaseDC_(0, hDC) PointSize = 12 ; MulDiv -> wilbert -> https://www.purebasic.fr/english/viewtopic.php?p=423001 lfHeight = -MulDiv(PointSize, DPI, 72) Debug lfHeight Debug -MulDiv(lfHeight, 72, DPI) ; reverse operation
Обновил программу:
Добавлено вычисление DPI и учёт при расчётах размера шрифта.
Отредактировано AZJIO (05.03.2022 14:16:11)
Поделиться502.04.2022 22:39:05
Что то непонятно в проге размер,размер +-,это что?как бы шрифт отрисовывается куда то там в контекст(окна или памяти) и он там как бы должен быть установлен?
Поделиться603.04.2022 07:37:32
Шрифт не в контекст отрисовывается, а меняется в системе, в ОС, это глобальное изменение шрифта. То же самое если открыть настройки шрифта в панели управления. Прописывается это в реестр. Размер1 и размер2 это разный тип, в диалоге выбора шрифта он определяется дюймами/сантиметрами, а в реестр прописывается в пикселах. Так как DPI может быть разный, то при одном и том же размере в сантиметрах размер в пикселах может быть разный. В браузере например указывается размер в пикселах, то есть 16, а в винде в сантиметрах, поэтому один и то же размер 12 в блокноте и 16 в браузере по размеру одинаковы. Поэтому я и вывел 2 размера чтобы юзер понимал что у него пропишется. В диалоге выбора выбираешь 12, а в столбце где 16 будет зависеть от DPI и там может быть другое значение.
Поделиться721.04.2022 16:32:42
MulDiv
ФУнкция muldiv() тупо делает операцию деления и умножения ,зачем вообще она нужна как функция если можно это сделать без неё?
Debug MulDiv_(100,50,20) Debug MulDiv_(100,50,10) Debug 100/20*50 Debug 100/10*50
Так браузер и блокнот это уже приложения поверх системы и там могут быть свои шрифты с размерами установлены.
а общий размер системы их наверное рассчитывается от значений экрана?
Structure test_displey displey_HORZSIZE_mm.i;Ширина физического экрана в миллиметрах. displey_vertsize_mm.i;Высота физического экрана в миллиметрах. displey_pixel_po_x.i;Количество пикселей на логический дюйм по ширине экрана. В системе с несколькими мониторами это значение одинаково для всех мониторов. displey_pixel_po_y.i;Количество пикселей на логический дюйм по высоте экрана. В системе с несколькими мониторами это значение одинаково для всех мониторов. displey_hrift_count.i;Количество шрифтов для конкретного устройства. EndStructure Global test.test_displey Procedure Test_contexst_displey(hwnd.i=0) hdc = GetDC_(hwnd) ; If hdc test\displey_HORZSIZE_mm= GetDeviceCaps_(hdc,#HORZSIZE) test\displey_vertsize_mm=GetDeviceCaps_(hdc,#VERTSIZE) test\displey_pixel_po_x=GetDeviceCaps_(hdc,#LOGPIXELSX) test\displey_pixel_po_y=GetDeviceCaps_(hdc,#LOGPIXELSY) test\displey_hrift_count=GetDeviceCaps_(hdc,#NUMFONTS) ReleaseDC_(hwnd,hdc) EndIf EndProcedure Test_contexst_displey() Desktop device context ps:скачал прогу и вижу работу с контекстом рисования а говорил ранее зачем он?
Отредактировано Sergeihik (21.04.2022 19:53:52)
Поделиться821.04.2022 21:48:37
ФУнкция muldiv() тупо
В теории операция производится точная, и округляется результат. Например 100/20 можно потерять десятые доли, а при умножении потерять эти десятые доли которые могли бы возвратится в целое число. Правильнее сначала умножить, а потом разделить, тогда доли не потеряются. Не важно это формула вычисления процента без потерь. Я просто не стал узнавать недостатки этой комбинации 100*50/20, а просто поверил автору wilbert, так как он постоянно выдаёт шедевральный код с использованием ASM в том числе.
Поделиться923.04.2022 12:46:44
ФУнкция muldiv() тупо делает операцию деления и умножения ,зачем вообще она нужна как функция если можно это сделать без неё?
Я не смотрел, как это делает данная функция, но основная проблема в том, что при умножении можно получить переполнение. Поэтому процессорные команды умножения кладут результат в пару регистров (результат двойной точности). Обратным образом работают команды деления - значения в паре регистров делится на значение одинарной точности. По идее, данная функция должна возвращать результат умножения и затем деления через промежуточную двойную точность. Надо будет потом проверить.
Поделиться1024.04.2022 22:15:49
Я не смотрел, как это делает данная функция, но основная проблема в том, что при умножении можно получить переполнение. Поэтому процессорные команды умножения кладут результат в пару регистров (результат двойной точности). Обратным образом работают команды деления - значения в паре регистров делится на значение одинарной точности. По идее, данная функция должна возвращать результат умножения и затем деления через промежуточную двойную точность. Надо будет потом проверить.
Да какая там особо точность она делает банально умножение а потом деление(это как бы из самого названия напрашивается) и результат округляет ,это я сам неправильно написал формулу хоть и подошёл результат,вот сразу понятно Debug MulDiv_(12,96,72)
и кода немного набросал
Procedure.s debug_ohibka(s.s)
Protected Buffer.s = Space(200)
FormatMessage_(#FORMAT_MESSAGE_FROM_SYSTEM,0, GetLastError_(), #LANG_NEUTRAL, @Buffer, 200,0)
Debug s+" "+Buffer
EndProcedure
Global lgf.logfont
Global hdc.i=GetWindowDC_(0)
debug_ohibka("GetWindowDC_()")
;
;
Global Buffers.s = Space(200)
GetTextFace_(hdc,200,@Buffers);извлекает имя гарнитуры шрифта, выбранного в указанном контексте устройства.
debug_ohibka("GetTextFace_()")
Debug "имя гарнитуры шрифта "+Buffers
;
;
Global dpi.i=GetDeviceCaps_(hdc,#LOGPIXELSY)
debug_ohibka("GetDeviceCaps_()")
Debug "dpi "+Str(dpi)
;
Global Size2.Size
GetTextExtentPoint32_(hdc,@"SВРQgjЩрRt9",11,@Size2);вычисляет ширину и высоту указанной строки текста.
debug_ohibka("GetTextExtentPoint32_()")
Debug "логическая высота символа "+Str(Size2\cy)+" ширина "+Str(Size2\cx/11)
;
;
Global TEXTMETRIC.TEXTMETRIC
GetTextMetrics_(hdc,@TEXTMETRIC);заполняет указанный буфер метриками для текущего выбранного шрифта.
debug_ohibka("GetTextMetrics_()")
Debug "Физическая высота символа "+Str(TEXTMETRIC\tmHeight)
;
;
SystemParametersInfo_(#SPI_GETICONTITLELOGFONT,0,@lgf,0)
debug_ohibka("SystemParametersInfo_()")
;
;
Global mode.i=GetMapMode_(hdc)
debug_ohibka("GetMapMode_()")
Select mode
Case #MM_TEXT;Каждая логическая единица сопоставляется с одним пикселем устройства. Положительный x справа; положительный y вниз.
Debug "#MM_TEXT"
Debug "логическая высота символа "+Str(Size2\cy)+ " Физическая высота символа "+Str(TEXTMETRIC\tmHeight)
Case #MM_LOMETRIC;Каждая логическая единица отображается на 0,1 миллиметра. Положительный x справа; положительный y вверх.
Debug "#MM_LOMETRIC"
Case #MM_HIMETRIC;Каждая логическая единица сопоставляется с 0,01 миллиметра. Положительный x справа; положительный y вверх.
Debug "#MM_HIMETRIC"
Case #MM_LOENGLISH;Каждая логическая единица соответствует 0,01 дюйма. Положительный x справа; положительный y вверх.
Debug "#MM_LOENGLISH"
Case #MM_HIENGLISH;Каждая логическая единица соответствует 0,001 дюйма. Положительный x справа; положительный y вверх.
Debug "#MM_HIENGLISH"
Case #MM_TWIPS;Каждая логическая единица сопоставляется с одной двадцатой точки принтера (1/1440 дюйма, также называемой «twip»). Положительный x справа; положительный y вверх.
Debug "#MM_TWIPS"
Case #MM_ISOTROPIC;Логические единицы сопоставляются с произвольными единицами с одинаково масштабируемыми осями; то есть одна единица по оси x равна одной единице по оси y. Используйте функции SetWindowExtEx и SetViewportExtEx , чтобы указать единицы измерения и ориентацию осей.
Debug "#MM_ISOTROPIC"
Case #MM_ANISOTROPIC;Логические единицы сопоставляются с произвольными единицами с произвольно масштабируемыми осями. Используйте функции SetWindowExtEx и SetViewportExtEx , чтобы указать необходимые единицы измерения, ориентацию и масштабирование.
Debug "#MM_ANISOTROPIC"
EndSelect
Debug "lgf\lfHeight "+Str(lgf\lfHeight)
If lgf\lfHeight<0
;преобразовывая в пиксели приводит в соответствие его обсалютную величину сверяя с высотой символов доступных шрифтов
If mode=#MM_TEXT
height=-MulDiv_(lgf\lfHeight,dpi,72);минус типа инверсия знака
Debug "height "+Str(height)
EndIf
ElseIf lgf\lfHeight>0
;механизм отображения логического в физический шрифт(пиксели),сверяя с высотой ячейки доступных шрифтов
Else;=0 заданная по умолчанию значение высоты
EndIf
ReleaseDC_(hwnd,hdc)
debug_ohibka("ReleaseDC_()")
Ps: с 10 винды ещё есть какая то функция SystemParametersInfoForDpi
Отредактировано Sergeihik (24.04.2022 22:19:37)
Поделиться1125.04.2022 23:15:12
MulDiv умножает два 32-битных числа и делит полученный 64-битный результат на 32-битное число, окpугляя получаемое значение до длижайшего целого. Может использоваться для избежания ошибки переполнения
Код:' Демострация того, как избежать ошибки переполнения Dim result As Long ' Без функции MulDiv вы получите ошибку переполнения ' так как результать умножения превышает 32-битное значение 'result = -134217728 * 243 / 110592 ' строка закомментирована ' С MulDiv вы можете избежать этой ошибки result = MulDiv(-134217728, 243, 110592)
Конкретно этот пример одинаково работает в PB что с функцией что без нее.
x.l = -134217728 * 243 / 110592 Debug x Debug MulDiv_(-134217728, 243, 110592)
Но если результат умножения не поместится с 32-ух битную переменную, в x86 приложениях не используя quad будет неправильный расчет.
Поделиться1226.04.2022 05:50:33
SystemParametersInfo Видимо работает только с системным шрифтом,во первых нет контекста hdc в функции, и getdc()создаёт изначально контекст с системным шрифтом
а далее сменив MapMode без установленного шрифта наверное оставит системный а если сменить шрифт на свой то SystemParametersInfo всё равно на системный выдаёт.
Да и GetTextMetrics в tmHeight похоже тоже логическую высоту выдаёт а не физическую.
Procedure.s debug_ohibka(s.s)
Protected Buffer.s = Space(200)
FormatMessage_(#FORMAT_MESSAGE_FROM_SYSTEM,0, GetLastError_(), #LANG_NEUTRAL, @Buffer, 200,0)
Debug s+" "+Buffer
EndProcedure
Procedure Test_hrift(hhdcc)
Protected lgf.logfont
Protected hdc.i=hhdcc;GetWindowDC_(0)
debug_ohibka("GetWindowDC_()")
;
Protected dpi.i=GetDeviceCaps_(hdc,#LOGPIXELSY)
debug_ohibka("GetDeviceCaps_()")
Debug "dpi экрана "+Str(dpi)
;
Protected Buffers.s = Space(200)
GetTextFace_(hdc,200,@Buffers);извлекает имя гарнитуры шрифта, выбранного в указанном контексте устройства.
debug_ohibka("GetTextFace_()")
Debug "имя гарнитуры шрифта "+Buffers
;
Protected Size2.Size
GetTextExtentPoint32_(hdc,@"SВРQgjЩрRt9",11,@Size2);вычисляет логическую ширину и высоту указанной строки текста.
debug_ohibka("GetTextExtentPoint32_()")
Debug "логическая высота символа "+Str(Size2\cy)+" логическая ширина "+Str(Size2\cx/11)
;
;
Protected TEXTMETRIC.TEXTMETRIC
GetTextMetrics_(hdc,@TEXTMETRIC);заполняет указанный буфер метриками для текущего выбранного шрифта.
debug_ohibka("GetTextMetrics_()")
Debug "Физическая высота символа "+Str(TEXTMETRIC\tmHeight)
Debug Str(TEXTMETRIC\tmAscent)
Debug Str(TEXTMETRIC\tmDigitizedAspectX);видимо dpi экрана
Protected mode.i=GetMapMode_(hdc)
debug_ohibka("GetMapMode_()")
Select mode
Case #MM_TEXT;Каждая логическая единица сопоставляется с одним пикселем устройства. Положительный x справа; положительный y вниз.
Debug "#MM_TEXT"
Debug "логическая высота символа "+Str(Size2\cy)+ " Физическая высота символа "+Str(TEXTMETRIC\tmHeight)
Case #MM_LOMETRIC;Каждая логическая единица отображается на 0,1 миллиметра. Положительный x справа; положительный y вверх.
Debug "#MM_LOMETRIC"
Debug "логическая высота символа "+Str(Size2\cy)+ " Физическая высота символа "+Str(TEXTMETRIC\tmHeight)
Case #MM_HIMETRIC;Каждая логическая единица сопоставляется с 0,01 миллиметра. Положительный x справа; положительный y вверх.
Debug "#MM_HIMETRIC"
Debug "логическая высота символа "+Str(Size2\cy)+ " Физическая высота символа "+Str(TEXTMETRIC\tmHeight)
Case #MM_LOENGLISH;Каждая логическая единица соответствует 0,01 дюйма. Положительный x справа; положительный y вверх.
Debug "#MM_LOENGLISH"
Debug "логическая высота символа "+Str(Size2\cy)+ " Физическая высота символа "+Str(TEXTMETRIC\tmHeight)
Case #MM_HIENGLISH;Каждая логическая единица соответствует 0,001 дюйма. Положительный x справа; положительный y вверх.
Debug "#MM_HIENGLISH"
Debug "логическая высота символа "+Str(Size2\cy)+ " Физическая высота символа "+Str(TEXTMETRIC\tmHeight)
Case #MM_TWIPS;Каждая логическая единица сопоставляется с одной двадцатой точки принтера (1/1440 дюйма, также называемой «twip»). Положительный x справа; положительный y вверх.
Debug "#MM_TWIPS"
Debug "логическая высота символа "+Str(Size2\cy)+ " Физическая высота символа "+Str(TEXTMETRIC\tmHeight)
Case #MM_ISOTROPIC;Логические единицы сопоставляются с произвольными единицами с одинаково масштабируемыми осями; то есть одна единица по оси x равна одной единице по оси y. Используйте функции SetWindowExtEx и SetViewportExtEx , чтобы указать единицы измерения и ориентацию осей.
Debug "#MM_ISOTROPIC"
Debug "логическая высота символа "+Str(Size2\cy)+ " Физическая высота символа "+Str(TEXTMETRIC\tmHeight)
Case #MM_ANISOTROPIC;Логические единицы сопоставляются с произвольными единицами с произвольно масштабируемыми осями. Используйте функции SetWindowExtEx и SetViewportExtEx , чтобы указать необходимые единицы измерения, ориентацию и масштабирование.
Debug "#MM_ANISOTROPIC"
Debug "логическая высота символа "+Str(Size2\cy)+ " Физическая высота символа "+Str(TEXTMETRIC\tmHeight)
EndSelect
;
SystemParametersInfo_(#SPI_GETICONTITLELOGFONT,0,@lgf,0)
debug_ohibka("SystemParametersInfo_()")
;
Debug "lgf\lfHeight "+Str(lgf\lfHeight)
If lgf\lfHeight<0
;преобразовывая в пиксели приводит в соответствие его обсалютную величину сверяя с высотой символов доступных шрифтов
; If mode=#MM_TEXT
height=-MulDiv_(lgf\lfHeight,dpi,72);минус типа инверсия знака
Debug "height "+Str(height)
;EndIf
ElseIf lgf\lfHeight>0
;механизм отображения логического в физический шрифт(пиксели),сверяя с высотой ячейки доступных шрифтов
Else;=0 заданная по умолчанию значение высоты
EndIf
;
Debug "=========================================="
EndProcedure
Global s1.s="!===Привет Пурик==="
Procedure Risuem_na_canvase(dc,s.s)
Static y.i
TextOut_(dc,10,y,@s,Len(s))
y-205
EndProcedure
Procedure.i canvascalbac(hwnd,msg,wparam,lparam)
Static PAINTSTRUCT.PAINTSTRUCT
Select msg
Case #WM_ERASEBKGND
Protected rect.rect
GetClientRect_(hwnd,@rect)
FillRect_(PAINTSTRUCT\hdc,@rect,$755555)
ProcedureReturn 0
Case #WM_PAINT
BeginPaint_(hwnd,@PAINTSTRUCT)
;Debug PAINTSTRUCT\hdc
;Risuem_na_canvase(PAINTSTRUCT\hdc,s1)
EndPaint_(hwnd,@PAINTSTRUCT)
ProcedureReturn 0
EndSelect
ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure
OpenWindow(0, 0, 0, 800, 400, "Testhrift",#PB_Window_SystemMenu| #PB_Window_SizeGadget | #PB_Window_MinimizeGadget| #PB_Window_MaximizeGadget | #PB_Window_ScreenCentered)
CanvasGadget(0,0,0,400,400)
If (GetClassLong_(GadgetID(0),#GCL_STYLE) & #CS_OWNDC)=0;если в классе созданного гаджета контекст переменный
SetClassLong_(GadgetID(0),#GCL_STYLE, #CS_GLOBALCLASS|#CS_VREDRAW | #CS_HREDRAW |#CS_SAVEBITS| #CS_BYTEALIGNCLIENT |#CS_OWNDC);установим постоянный контекст
DestroyWindow_(GadgetID(0));убьём окно
;и пересоздадим уже с постоянным контекстом рисования
CanvasGadget(0,0,0,800,400)
SetWindowLongPtr_(GadgetID(0),#GWLP_WNDPROC,@canvascalbac());заменим тупо на свой обработчик
EndIf
Global hdc.i=GetDC_(GadgetID(0));GetDCEx_(GadgetID(0),0,#DCX_CACHE|#DCX_CLIPCHILDREN|#DCX_CLIPSIBLINGS);получить контекст рисования
Debug "dc "+Str(hdc)
Global hrift.i=CreateFont_(44,0,0,0,0,0,0,0,0,0,0,0,0,"Lucida Sansunicode");создадим шрифт
;SelectObject_(hdc,hrift);установим шрифт
SetTextColor_(hdc,$A33B33);устанавливает цвет текста в строке
SetBkColor_(hdc,$223BE9);цвет фона строки
Test_hrift(hdc);посмотрим системный
SelectObject_(hdc,hrift);установим шрифт
;нарисуем ка канвасе
SetMapMode_(hdc,#MM_TEXT);установим режим преобразования
Risuem_na_canvase(hdc,s1+"#MM_TEXT")
Test_hrift(hdc)
SetMapMode_(hdc,#MM_LOMETRIC);установим режим преобразования
Risuem_na_canvase(hdc,s1+"#MM_LOMETRIC")
Test_hrift(hdc)
SetMapMode_(hdc,#MM_LOENGLISH);установим режим преобразования
Risuem_na_canvase(hdc,s1+"#MM_LOENGLISH")
Test_hrift(hdc)
Repeat
Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
DeleteObject_(Hrift)
ReleaseDC_(GadgetID(0),hdc)
Поделиться1328.04.2022 23:35:18
Да какая там особо точность она делает банально умножение а потом деление(это как бы из самого названия напрашивается) и результат округляет
Я Вам написал КАК работают операции умножения и деления. И подобные двойные функции в языках программирования высокого уровня нужны именно для того, чтобы избежать переполнения в Вашем "банальном" умножении.
