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
Да какая там особо точность она делает банально умножение а потом деление(это как бы из самого названия напрашивается) и результат округляет
Я Вам написал КАК работают операции умножения и деления. И подобные двойные функции в языках программирования высокого уровня нужны именно для того, чтобы избежать переполнения в Вашем "банальном" умножении.