PureBasic - форум

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » PureBasic - форум » PureBasic для Windows » WindowsFont


WindowsFont

Сообщений 1 страница 13 из 13

1

WindowsFont

Изменение шрифта в интерфейсе Windows.

Скачать: yadi.sk, upload.ee

https://i.imgur.com/Jojpkl1.png

Обновление:
Добавил кнопку экспорт данных, чтобы бэкапить перед использованием.

Отредактировано AZJIO (05.03.2022 01:26:25)

0

2

Обнолвение
Изменение размера и названия шрифта в имёнах файлов и папок в эксплорере применяется мгновенно, остальное требует выход/вход пользователя.
Поддерживается изменение размера окна.

В каком то смысле это позволяет подбирать размер шрифта. И во вторых лично мне в 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)

0

3

AZJIO написал(а):

SystemParametersInfo_(#SPI_SET....,  0, @spinfo, 0)

попытался этим воспользоваться, всё накрылось медным тазом, после перезагрузки само всё восстановилось
надо думать что то неправильно я делал
пока бросил эту затею

Код:
lfHeight = -MulDiv(PointSize, GetDeviceCaps(hDC, #LOGPIXELSY), 72)

код возвращает размер шрифта который мы видим в редакторах при выборе шрифта

0

4

Итак, методом тыка и гуглингом выяснил следующее:
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)

0

5

Что то непонятно в проге размер,размер +-,это что?как бы шрифт отрисовывается куда то там в контекст(окна или памяти) и он там как бы должен быть установлен?

0

6

Шрифт не в контекст отрисовывается, а меняется в системе, в ОС, это глобальное изменение шрифта. То же самое если открыть настройки шрифта в панели управления. Прописывается это в реестр. Размер1 и размер2 это разный тип, в диалоге выбора шрифта он определяется дюймами/сантиметрами, а в реестр прописывается в пикселах. Так как DPI может быть разный, то при одном и том же размере в сантиметрах размер в пикселах может быть разный. В браузере например указывается размер в пикселах, то есть 16,  а в винде в сантиметрах, поэтому один и то же размер 12 в блокноте и 16 в браузере по размеру одинаковы. Поэтому я и вывел 2 размера чтобы юзер понимал что у него пропишется. В диалоге выбора выбираешь 12, а в столбце где 16 будет зависеть от DPI и там может быть другое значение.

0

7

AZJIO написал(а):

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)

0

8

Sergeihik написал(а):

ФУнкция muldiv() тупо

В теории операция производится точная, и округляется результат. Например 100/20 можно потерять десятые доли, а при умножении потерять эти десятые доли которые могли бы возвратится в целое число. Правильнее сначала умножить, а потом разделить, тогда доли не потеряются. Не важно это формула вычисления процента без потерь. Я просто не стал узнавать недостатки этой комбинации 100*50/20, а просто поверил автору wilbert, так как он постоянно выдаёт шедевральный код с использованием ASM в том числе.

0

9

Sergeihik написал(а):

ФУнкция muldiv() тупо делает операцию деления и умножения ,зачем вообще она нужна как функция если можно это сделать без неё?

Я не смотрел, как это делает данная функция, но основная проблема в том, что при умножении можно получить переполнение. Поэтому процессорные команды умножения кладут результат в пару регистров (результат двойной точности). Обратным образом работают команды деления - значения в паре регистров делится на значение одинарной точности. По идее, данная функция должна возвращать результат умножения и затем деления через промежуточную двойную точность. Надо будет потом проверить.

0

10

Smitis написал(а):

Я не смотрел, как это делает данная функция, но основная проблема в том, что при умножении можно получить переполнение. Поэтому процессорные команды умножения кладут результат в пару регистров (результат двойной точности). Обратным образом работают команды деления - значения в паре регистров делится на значение одинарной точности. По идее, данная функция должна возвращать результат умножения и затем деления через промежуточную двойную точность. Надо будет потом проверить.

Да какая там особо точность она делает банально умножение а потом деление(это как бы из самого названия напрашивается) и результат округляет ,это я сам неправильно написал формулу хоть и подошёл результат,вот сразу понятно 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)

0

11

Пишут

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 будет неправильный расчет.

0

12

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)

0

13

Sergeihik написал(а):

Да какая там особо точность она делает банально умножение а потом деление(это как бы из самого названия напрашивается) и результат округляет

Я Вам написал КАК работают операции умножения и деления. И подобные двойные функции в языках программирования высокого уровня нужны именно для того, чтобы избежать переполнения в Вашем "банальном" умножении.

0


Вы здесь » PureBasic - форум » PureBasic для Windows » WindowsFont