Update Manifest in Executable

Share your advanced PureBasic knowledge/code with the community.
User avatar
ChrisR
Enthusiast
Enthusiast
Posts: 409
Joined: Sun Jan 08, 2017 10:27 pm
Location: France

Update Manifest in Executable

Post by ChrisR »

A small tool to Update the DPIaware Manifest in Executable
A new exe is created with the file name according to the chosen options
To be completed with other options: requireAdministrator, asInvoker,...

Code: Select all

; -----------------------------------------------------------------------------
;           Name: UpdateManifest.pb
;    Description: Update DPI Manifest in Executable
;         Author: ChrisR
;           Date: 2021-10-15
;             OS: Windows
;             PB: 5.73 LTS
; -----------------------------------------------------------------------------

EnableExplicit

UsePNGImageDecoder()

#SCS_32BIT_BINARY = 0
#SCS_64BIT_BINARY = 6
#SCS_DOS_BINARY   = 1
#SCS_OS216_BINARY = 5
#SCS_PIF_BINARY   = 3
#SCS_POSIX_BINARY = 4
#SCS_WOW_BINARY   = 2

#DPI_Default      = 1
#DPI_RequireAdmin = 2
#DPI_asInvoker    = 4
#DPI_longPath     = 8
#DPI_Aware        = 16
#DPI_PerMonitor   = 32
#DPI_gdiScaling   = 64

;- Enumerations
Enumeration Window
  #MainWindow
EndEnumeration

Enumeration Gadgets
  #Txt_Path
  #String_Path
  #Btn_Path
  #Check_RequireAdmin
  #Image_RequireAdmin
  #Check_asInvoker
  #Image_asInvoker
  #Check_longPath
  #Image_longPath
  #Check_DPIAware
  #Image_DPIAware
  #Check_PerMonitor
  #Image_PerMonitor
  #Check_gdiscaling
  #Image_gdiscaling
  #Btn_Apply
  #Txt_Done
EndEnumeration

Enumeration Image
  #Valid_png
EndEnumeration

CatchImage(#Valid_png, ?Valid_png)

Global DPIrate.f

Macro DPI(_xy_) : (_xy_) * DPIrate : EndMacro

;- Declare
Declare.f DPIrate()
Declare   ReqHeightModel(Model.s)
Declare   DPIawareManifest(FileName.s, ManifestFlag = #DPI_Default)
Declare   FindDPIResourceFlag(FileName.s)
Declare   Open_MainWindow_RequiredSize(X = 0, Y = 0, Width = 300, Height = 210)
Declare   Open_MainWindow(X = 0, Y = 0, Width = 300, Height = 210)

Procedure.f DPIrate()
  Define TmpImage.i
  Static fPpp.f
  If fPpp = 0
    TmpImage = CreateImage(#PB_Any,1,1)
    If IsImage(TmpImage)
      If StartVectorDrawing(ImageVectorOutput(TmpImage))
        fPpp = VectorResolutionX()
        StopVectorDrawing()
      EndIf
      FreeImage(TmpImage)
    EndIf
  EndIf
  ProcedureReturn fPpp / 96
EndProcedure

Procedure ReqHeightModel(Model.s)
  Protected TempGadget.i, ReqHeight.i, DummyText.s = "ABC123"
  Select Model
    Case "ButtonGadget"
      TempGadget = ButtonGadget     (#PB_Any, 0, 0, 25, 25, DummyText)
    Case "ButtonImageGadget"
      TempGadget = ButtonImageGadget(#PB_Any, 0, 0, 25, 25, ImageID(#Valid_png))
    Case "CheckBoxGadget"  
      TempGadget = CheckBoxGadget   (#PB_Any, 0, 0, 25, 25, DummyText)
    Case "ComboBoxGadget"
      TempGadget = ComboBoxGadget   (#PB_Any, 0, 0, 25, 25, #PB_ComboBox_Editable)
      SetGadgetText(TempGadget, DummyText)
    Case "TextGadget"
      TempGadget = TextGadget       (#PB_Any, 0, 0, 25, 25, DummyText)
    Case "SpinGadget"
      TempGadget = SpinGadget       (#PB_Any, 0, 0, 25, 25, 0, 1000, #PB_Spin_ReadOnly)
    Case "StringGadget"
      TempGadget = StringGadget     (#PB_Any, 0, 0, 25, 25, DummyText)
    Case "TextGadget"
      TempGadget = TextGadget       (#PB_Any, 0, 0, 25, 25, DummyText)
  EndSelect
  If IsGadget(TempGadget)
    ReqHeight = GadgetHeight(TempGadget, #PB_Gadget_RequiredSize)
    FreeGadget(TempGadget)
  EndIf
  ProcedureReturn ReqHeight
EndProcedure

ProcedureDLL FindDPIResourceFlag(FileName.s)
  Protected Manifest.s, Handle.i, HandleResource.i, HandleLoadResource, HandleLoadResourceSize.i, ManifestFlag.i
  Handle = LoadLibraryEx_(@FileName, 0, #LOAD_LIBRARY_AS_DATAFILE)  ; Handle = LoadLibrary_(@FileName)
  If Handle
    HandleResource = FindResource_(Handle, 1, #RT_MANIFEST)
    If HandleResource
      HandleLoadResource = LoadResource_(Handle, HandleResource)
      HandleLoadResourceSize = SizeofResource_(Handle, HandleResource)
      Manifest = PeekS(HandleLoadResource, HandleLoadResourceSize, #PB_UTF8)
      If FindString(Manifest, "requireAdministrator")           : ManifestFlag + #DPI_RequireAdmin : EndIf
      If FindString(Manifest, "asInvoker")                      : ManifestFlag + #DPI_asInvoker    : EndIf
      If FindString(Manifest, "longPathAware>true")             : ManifestFlag + #DPI_longPath    : EndIf
      If FindString(Manifest, "<dpiAware>true</dpiAware>")      : ManifestFlag + #DPI_Aware        : EndIf
      If FindString(Manifest, "<dpiAware>true/PM</dpiAware>")   : ManifestFlag + #DPI_Aware        : EndIf
      If FindString(Manifest, "<dpiAwareness>PerMonitor")       : ManifestFlag + #DPI_PerMonitor   : EndIf
      If FindString(Manifest, "<gdiScaling>false</gdiScaling>") : ManifestFlag + #DPI_gdiScaling   : EndIf
      FreeLibrary_(Handle)
      ProcedureReturn ManifestFlag
    EndIf
  EndIf
EndProcedure

Procedure DPIawareManifest(FileName.s, ManifestFlag = #DPI_Default)
  Protected NewFileName.s, Handle.i, lpBinaryType.i, ProcessorArch.s, *Buffer, ManifestXML.s, Manifest.s, LenManifest.i 
  
  If FileSize(FileName) = -1
    ProcedureReturn #False
  EndIf
  
  NewFileName = GetPathPart(FileName) + GetFilePart(FileName , #PB_FileSystem_NoExtension)
  If ManifestFlag & #DPI_RequireAdmin : NewFileName + "_Admin"     : EndIf
  If ManifestFlag & #DPI_asInvoker    : NewFileName + "_asInvoker" : EndIf
  If ManifestFlag & #DPI_longPath     : NewFileName + "_Lpath"     : EndIf
  If ManifestFlag & #DPI_Aware Or ManifestFlag & #DPI_PerMonitor Or ManifestFlag & #DPI_gdiScaling
    NewFileName + "_DPIaware"
    If ManifestFlag & #DPI_PerMonitor : NewFileName + "PM"         : EndIf
    If ManifestFlag & #DPI_gdiScaling : NewFileName + "gdi"        : EndIf
  Else
    NewFileName + "_DPIunAware"
  EndIf
  NewFileName + "." + GetExtensionPart(FileName)
  
  If FileSize(NewFileName) > 0 : DeleteFile(NewFileName) : EndIf
  CopyFile(FileName, NewFileName)
  
  Handle = BeginUpdateResource_(@NewFileName, #False) 
  If Handle
    If GetBinaryType_(@NewFileName, @lpBinaryType)
      Select lpBinaryType
        Case #SCS_64BIT_BINARY : ProcessorArch = "amd64"
        Case #SCS_32BIT_BINARY : ProcessorArch = "X86"
      EndSelect
      
      ManifestXML     = "<?xml version=" +#DQUOTE$+ "1.0" +#DQUOTE$+ " encoding=" +#DQUOTE$+ "UTF-8" +#DQUOTE$+ " standalone=" +#DQUOTE$+ "yes" +#DQUOTE$+ "?>" +#CRLF$+
                        "<assembly xmlns=" +#DQUOTE$+ "urn:schemas-microsoft-com:asm.v1" +#DQUOTE$+ " manifestVersion=" +#DQUOTE$+ "1.0" +#DQUOTE$+ ">" +#CRLF$+
                        "  <assemblyIdentity" +#CRLF$+
                        "    version=" +#DQUOTE$+ "1.0.0.0" +#DQUOTE$+#CRLF$+
                        "    processorArchitecture=" +#DQUOTE$+ ProcessorArch +#DQUOTE$+#CRLF$+
                        "    name=" +#DQUOTE$+ "CompanyName.ProductName.YourApp" +#DQUOTE$+#CRLF$+
                        "    type=" +#DQUOTE$+ "win32" +#DQUOTE$+ " />" +#CRLF$+
                        "  <description></description>" +#CRLF$+
                        "  <dependency>" +#CRLF$+
                        "    <dependentAssembly>" +#CRLF$+
                        "      <assemblyIdentity" +#CRLF$+
                        "        type=" +#DQUOTE$+ "win32" +#DQUOTE$+#CRLF$+
                        "        name=" +#DQUOTE$+ "Microsoft.Windows.Common-Controls" +#DQUOTE$+#CRLF$+
                        "        version=" +#DQUOTE$+ "6.0.0.0" +#DQUOTE$+#CRLF$+
                        "        processorArchitecture=" +#DQUOTE$+ ProcessorArch +#DQUOTE$+#CRLF$+
                        "        publicKeyToken=" +#DQUOTE$+ "6595b64144ccf1df" +#DQUOTE$+#CRLF$+
                        "        language=" +#DQUOTE$+ "*" +#DQUOTE$+ " />" +#CRLF$+
                        "    </dependentAssembly>" +#CRLF$+
                        "  </dependency>" +#CRLF$
      
      If ManifestFlag & #DPI_RequireAdmin
        ManifestXML   + "  <trustInfo xmlns=" +#DQUOTE$+ "urn:schemas-microsoft-com:asm.v2" +#DQUOTE$+ ">" +#CRLF$+
                        "    <security>" +#CRLF$+
                        "      <requestedPrivileges>" +#CRLF$+
                        "        <requestedExecutionLevel" +#CRLF$+
                        "          level=" +#DQUOTE$+ "requireAdministrator" +#DQUOTE$+#CRLF$+
                        "          uiAccess=" +#DQUOTE$+ "false" +#DQUOTE$+ "/>" +#CRLF$+
                        "        </requestedPrivileges>" +#CRLF$+
                        "       </security>" +#CRLF$+
                        "  </trustInfo>" +#CRLF$
      EndIf
      
      If ManifestFlag & #DPI_asInvoker
        ManifestXML   + "  <trustInfo xmlns=" +#DQUOTE$+ "urn:schemas-microsoft-com:asm.v2" +#DQUOTE$+ ">" +#CRLF$+
                        "    <security>" +#CRLF$+
                        "      <requestedPrivileges>" +#CRLF$+
                        "        <requestedExecutionLevel" +#CRLF$+
                        "          level=" +#DQUOTE$+ "asInvoker" +#DQUOTE$+#CRLF$+
                        "          uiAccess=" +#DQUOTE$+ "false" +#DQUOTE$+ "/>" +#CRLF$+
                        "        </requestedPrivileges>" +#CRLF$+
                        "       </security>" +#CRLF$+
                        "  </trustInfo>" +#CRLF$
      EndIf
      
      If ManifestFlag & #DPI_longPath Or ManifestFlag & #DPI_Aware Or ManifestFlag & #DPI_PerMonitor Or ManifestFlag & #DPI_gdiScaling
        ManifestXML   + "  <asmv3:application xmlns:asmv3=" +#DQUOTE$+ "urn:schemas-microsoft-com:asm.v3" +#DQUOTE$+ ">" +#CRLF$
      EndIf
      
      If ManifestFlag & #DPI_longPath
        ManifestXML   + "    <asmv3:windowsSettings xmlns:ws2=" +#DQUOTE$+ "http://schemas.microsoft.com/SMI/2016/WindowsSettings" +#DQUOTE$+ ">" +#CRLF$+
                        "      <ws2:longPathAware>true</ws2:longPathAware>" +#CRLF$+
                        "    </asmv3:windowsSettings>" +#CRLF$
      EndIf
      
      If ManifestFlag & #DPI_Aware And ManifestFlag & #DPI_PerMonitor
        ManifestXML   + "    <asmv3:windowsSettings xmlns=" +#DQUOTE$+ "http://schemas.microsoft.com/SMI/2005/WindowsSettings" +#DQUOTE$+ ">" +#CRLF$+
                        "      <dpiAware>true/PM</dpiAware>" +#CRLF$+
                        "    </asmv3:windowsSettings>" +#CRLF$
      ElseIf ManifestFlag & #DPI_Aware
        ManifestXML   + "    <asmv3:windowsSettings xmlns=" +#DQUOTE$+ "http://schemas.microsoft.com/SMI/2005/WindowsSettings" +#DQUOTE$+ ">" +#CRLF$+
                        "      <dpiAware>true</dpiAware>" +#CRLF$+
                        "    </asmv3:windowsSettings>" +#CRLF$
      EndIf
      
      If ManifestFlag & #DPI_PerMonitor
        ManifestXML   + "    <asmv3:windowsSettings xmlns=" +#DQUOTE$+ "http://schemas.microsoft.com/SMI/2016/WindowsSettings" +#DQUOTE$+ ">" +#CRLF$+
                        "      <dpiAwareness>PerMonitorV2,PerMonitor</dpiAwareness>" +#CRLF$+
                        "    </asmv3:windowsSettings>" +#CRLF$
      EndIf
      
      If ManifestFlag & #DPI_gdiScaling
        ManifestXML   + "    <asmv3:windowsSettings xmlns=" +#DQUOTE$+ "http://schemas.microsoft.com/SMI/2017/WindowsSettings" +#DQUOTE$+ ">" +#CRLF$+
                        "      <gdiScaling>false</gdiScaling>" +#CRLF$+
                        "    </asmv3:windowsSettings>" +#CRLF$
      EndIf
      
      If ManifestFlag & #DPI_longPath Or ManifestFlag & #DPI_Aware Or ManifestFlag & #DPI_PerMonitor Or ManifestFlag & #DPI_gdiScaling
        ManifestXML   + "  </asmv3:application>" +#CRLF$
      EndIf
      ManifestXML       + "</assembly>"
      
      *Buffer = UTF8(ManifestXML)
      Manifest = PeekS(*Buffer, -1)
      FreeMemory(*Buffer)
      ; *Buffer = AllocateMemory(StringByteLength(ManifestXML) + SizeOf(Character))
      ; If *Buffer : PokeS(*Buffer, ManifestXML, -1, #PB_UTF8) : Manifest = PeekS(*Buffer, -1) : FreeMemory(*Buffer) : EndIf
      
      LenManifest = StringByteLength(Manifest, #PB_Unicode)
      ;ShowMemoryViewer(@Manifest, LenManifest) : Debug GetFilePart(NewFileName) + " Manifest Last Char : " + Right(Manifest, 1)
      If Right(Manifest, 1) = ">" : LenManifest - 1 : EndIf
      
      UpdateResource_(Handle, #RT_MANIFEST, 1, 1033, @Manifest, LenManifest)
      EndUpdateResource_(Handle, #False)
      
      SetGadgetText(#Txt_Done, GetFilePart(NewFileName) +#CRLF$+ "Successfully Created :)")
      ProcedureReturn #True
    EndIf
  EndIf
  
EndProcedure

Procedure Open_MainWindow_RequiredSize(X = 0, Y = 0, Width = 300, Height = 210)
  Protected yy.i, ReqHeight_Text.i, ReqHeight_String.i, ReqHeight_Button.i, ReqHeight_Check.i, ReqHeight_BtnImg.i
  If OpenWindow(#MainWindow,            X,        Y,         Width,             Height, "Update Manifest in Executable", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    ReqHeight_Text   = ReqHeightModel("TextGadget")
    ReqHeight_String = ReqHeightModel("StringGadget")
    ReqHeight_Button = ReqHeightModel("ButtonGadget")
    ReqHeight_Check  = ReqHeightModel("CheckBoxGadget")
    ReqHeight_BtnImg = ReqHeightModel("ButtonImageGadget")
    yy = 5
    TextGadget(#Txt_Path,               DPI(10),  DPI(yy),   DPI(150),          ReqHeight_Text,   "Exe Path:") : yy + ReqHeight_Text
    StringGadget(#String_Path,          DPI(10),  DPI(yy),   DPI(255),          ReqHeight_String, "", #PB_String_ReadOnly)
    ButtonGadget(#Btn_Path,             DPI(270), DPI(yy-2), ReqHeight_Button,  ReqHeight_Button, "...") : yy + ReqHeight_Button
    yy + 2
    CheckBoxGadget(#Check_RequireAdmin, DPI(10),  DPI(yy),   DPI(255),          ReqHeight_Check,  "Request Administrator mode (Vista+)") : DisableGadget(#Check_RequireAdmin, #True)
    ImageGadget(#Image_RequireAdmin,    DPI(270), DPI(yy-2), ReqHeight_BtnImg,  ReqHeight_BtnImg, 0) : yy + ReqHeight_Check
    CheckBoxGadget(#Check_asInvoker,    DPI(10),  DPI(yy),   DPI(255),          ReqHeight_Check,  "Request User mode (Vista+)")          : DisableGadget(#Check_asInvoker,    #True)
    ImageGadget(#Image_asInvoker,       DPI(270), DPI(yy-2), ReqHeight_BtnImg,  ReqHeight_BtnImg, 0) : yy + ReqHeight_Check  
    CheckBoxGadget(#Check_longPath,     DPI(10),  DPI(yy),   DPI(255),          ReqHeight_Check,  "Request User mode (Vista+)")          : DisableGadget(#Check_longPath,     #True)
    ImageGadget(#Image_longPath,        DPI(270), DPI(yy-2), ReqHeight_BtnImg,  ReqHeight_BtnImg, 0) : yy + ReqHeight_Check     
    CheckBoxGadget(#Check_DPIAware,     DPI(10),  DPI(yy),   DPI(255),          ReqHeight_Check,  "DPI_Aware")                           : DisableGadget(#Check_DPIAware,     #True)
    ImageGadget(#Image_DPIAware,        DPI(270), DPI(yy-2), ReqHeight_BtnImg,  ReqHeight_BtnImg, 0) : yy + ReqHeight_Check
    CheckBoxGadget(#Check_PerMonitor,   DPI(10),  DPI(yy),   DPI(255),          ReqHeight_Check,  "PerMonitorV2 DPI_Aware")              : DisableGadget(#Check_PerMonitor,   #True)
    ImageGadget(#Image_PerMonitor,      DPI(270), DPI(yy-2), ReqHeight_BtnImg,  ReqHeight_BtnImg, 0) : yy + ReqHeight_Check
    CheckBoxGadget(#Check_gdiscaling,   DPI(10),  DPI(yy),   DPI(255),          ReqHeight_Check,  "gdiscaling (false)")                  : DisableGadget(#Check_gdiscaling,   #True)
    ImageGadget(#Image_gdiscaling,      DPI(270), DPI(yy-2), ReqHeight_BtnImg,  ReqHeight_BtnImg, 0) : yy + ReqHeight_Check
    yy + 2
    ButtonGadget(#Btn_Apply,            0,        DPI(yy),   WindowWidth(#MainWindow),           DPI(40),          "Apply Change")       : DisableGadget(#Btn_Apply, #True)
    TextGadget(#Txt_Done,               DPI(10),  DPI(yy),   WindowWidth(#MainWindow) - DPI(10), DPI(40),          "Done!")              : HideGadget(#Txt_Done, #True)
    yy + 40
    ResizeWindow(#MainWindow, #PB_Ignore, #PB_Ignore, #PB_Ignore, DPI(yy))
  EndIf
EndProcedure

Procedure Open_MainWindow(X = 0, Y = 0, Width = 300, Height = 210)
  Protected yy.i
  If OpenWindow(#MainWindow,            X,        Y,         Width,    Height, "Update Manifest in Executable", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    yy = 5
    TextGadget(#Txt_Path,               DPI(10),  DPI(yy),   DPI(150), DPI(17), "Exe Path:")           : yy + 17
    StringGadget(#String_Path,          DPI(10),  DPI(yy),   DPI(255), DPI(20), "", #PB_String_ReadOnly)
    ButtonGadget(#Btn_Path,             DPI(270), DPI(yy-2), DPI(24),  DPI(24), "...")                 : yy + 24
    yy + 2
    CheckBoxGadget(#Check_RequireAdmin, DPI(10),  DPI(yy),   DPI(255), DPI(20),  "Request Administrator mode (Vista+)") : DisableGadget(#Check_RequireAdmin, #True)
    ImageGadget(#Image_RequireAdmin,    DPI(270), DPI(yy-2), DPI(24),  DPI(24), 0)                     : yy + 20
    CheckBoxGadget(#Check_asInvoker,    DPI(10),  DPI(yy),   DPI(255), DPI(20),  "Request User mode (Vista+)")          : DisableGadget(#Check_asInvoker, #True)
    ImageGadget(#Image_asInvoker,       DPI(270), DPI(yy-2), DPI(24),  DPI(24), 0)                     : yy + 20
    CheckBoxGadget(#Check_longPath,     DPI(10),  DPI(yy),   DPI(255), DPI(20),  "Long Path Aware")                     : DisableGadget(#Check_longPath, #True)
    ImageGadget(#Image_longPath,        DPI(270), DPI(yy-2), DPI(24),  DPI(24), 0)                     : yy + 20
    CheckBoxGadget(#Check_DPIAware,     DPI(10),  DPI(yy),   DPI(255), DPI(20),  "DPI_Aware")                           : DisableGadget(#Check_DPIAware, #True)
    ImageGadget(#Image_DPIAware,        DPI(270), DPI(yy-2), DPI(24),  DPI(24), 0)                     : yy + 20
    CheckBoxGadget(#Check_PerMonitor,   DPI(10),  DPI(yy),   DPI(255), DPI(20),  "PerMonitorV2 DPI_Aware")                      : DisableGadget(#Check_PerMonitor, #True)
    ImageGadget(#Image_PerMonitor,      DPI(270), DPI(yy-2), DPI(24),  DPI(24), 0)                     : yy + 20
    CheckBoxGadget(#Check_gdiscaling,   DPI(10),  DPI(yy),   DPI(255), DPI(20),  "gdiscaling (false)")                      : DisableGadget(#Check_gdiscaling, #True)
    ImageGadget(#Image_gdiscaling,      DPI(270), DPI(yy-2), DPI(24),  DPI(24), 0)                     : yy + 20
    yy + 2
    ButtonGadget(#Btn_Apply,            0,        DPI(yy),   WindowWidth(#MainWindow),           DPI(40),          "Apply Change")       : DisableGadget(#Btn_Apply, #True)
    TextGadget(#Txt_Done,               DPI(10),  DPI(yy),   WindowWidth(#MainWindow) - DPI(10), DPI(40),          "Done!")              : HideGadget(#Txt_Done, #True)
    yy + 40
    ResizeWindow(#MainWindow, #PB_Ignore, #PB_Ignore, #PB_Ignore, DPI(yy))
  EndIf
EndProcedure

;- Main Program
Define FileName.s, ManifestFlag.i

DPIrate = DPIrate()
ResizeImage(#Valid_png, DPI(ImageWidth(#Valid_png)), DPI(ImageHeight(#Valid_png)),#PB_Image_Smooth)

;- Open MainWindow or RequiredSize
Open_MainWindow(0, 0, DPI(300), DPI(210))
;Open_MainWindow_RequiredSize(0, 0, DPI(300), DPI(210))

;- Event Loop
Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Break
      
    Case #PB_Event_Gadget
      Select EventGadget()
        Case #Btn_Path
          FileName = OpenFileRequester("Update Manifest in Executable", "", "Executable (*.exe)|*.exe",0 )
          SetGadgetText(#String_Path, FileName)
          If FileSize(FileName) > 1
            DisableGadget(#Check_RequireAdmin, #False) : DisableGadget(#Check_asInvoker, #False) : DisableGadget(#Check_longPath, #False)
            DisableGadget(#Check_DPIAware, #False) : DisableGadget(#Check_PerMonitor, #False) : DisableGadget(#Check_gdiscaling, #False)  : DisableGadget(#Btn_Apply, #False)
            HideGadget(#Btn_Apply, #False) : HideGadget(#Txt_Done, #True)
            ManifestFlag = FindDPIResourceFlag(FileName)
            If ManifestFlag & #DPI_RequireAdmin
              SetGadgetState(#Image_RequireAdmin, ImageID(#Valid_png)) : SetGadgetState(#Check_RequireAdmin, #PB_Checkbox_Checked)
            Else
              SetGadgetState(#Image_RequireAdmin, 0)                   : SetGadgetState(#Check_RequireAdmin, #PB_Checkbox_Unchecked)
            EndIf
            If ManifestFlag & #DPI_asInvoker
              SetGadgetState(#Image_asInvoker,    ImageID(#Valid_png)) : SetGadgetState(#Check_asInvoker,    #PB_Checkbox_Checked)
            Else
              SetGadgetState(#Image_asInvoker,    0)                   : SetGadgetState(#Check_asInvoker,    #PB_Checkbox_Unchecked)
            EndIf
            If ManifestFlag & #DPI_longPath
              SetGadgetState(#Image_longPath,     ImageID(#Valid_png)) : SetGadgetState(#Check_longPath,     #PB_Checkbox_Checked)
            Else
              SetGadgetState(#Image_longPath,     0)                   : SetGadgetState(#Check_longPath,     #PB_Checkbox_Unchecked)
            EndIf            
            If ManifestFlag & #DPI_Aware
              SetGadgetState(#Image_DPIAware,     ImageID(#Valid_png)) : SetGadgetState(#Check_DPIAware,     #PB_Checkbox_Checked)
            Else
              SetGadgetState(#Image_DPIAware,     0)                   : SetGadgetState(#Check_DPIAware,     #PB_Checkbox_Unchecked)
            EndIf
            If ManifestFlag & #DPI_PerMonitor
              SetGadgetState(#Image_PerMonitor,   ImageID(#Valid_png)) : SetGadgetState(#Check_PerMonitor,   #PB_Checkbox_Checked)
            Else
              SetGadgetState(#Image_PerMonitor,   0)                   : SetGadgetState(#Check_PerMonitor,   #PB_Checkbox_Unchecked)
            EndIf
            If ManifestFlag & #DPI_gdiScaling
              SetGadgetState(#Image_gdiscaling,   ImageID(#Valid_png)) : SetGadgetState(#Check_gdiscaling,   #PB_Checkbox_Checked)
            Else
              SetGadgetState(#Image_gdiscaling,   0)                   : SetGadgetState(#Check_gdiscaling,   #PB_Checkbox_Unchecked)
            EndIf
          Else
            DisableGadget(#Check_RequireAdmin, #True) : DisableGadget(#Check_asInvoker, #True) : DisableGadget(#Check_longPath, #True)
            DisableGadget(#Check_DPIAware, #True)     : DisableGadget(#Check_PerMonitor, #True) : DisableGadget(#Check_gdiscaling, #True)  : DisableGadget(#Btn_Apply, #True)
            HideGadget(#Btn_Apply, #False)            : HideGadget(#Txt_Done, #True)
            SetGadgetState(#Image_DPIAware, 0)        : SetGadgetState(#Image_PerMonitor, 0)    : SetGadgetState(#Image_gdiscaling, 0)
            SetGadgetState(#Check_DPIAware, #PB_Checkbox_Unchecked) : SetGadgetState(#Check_PerMonitor, #PB_Checkbox_Unchecked) : SetGadgetState(#Check_gdiscaling, #PB_Checkbox_Unchecked)
          EndIf
          
        Case #Check_RequireAdmin
          If GetGadgetState(#Check_RequireAdmin) = #PB_Checkbox_Checked
            SetGadgetState(#Check_asInvoker,       #PB_Checkbox_Unchecked)
          EndIf
        Case #Check_asInvoker
          If GetGadgetState(#Check_asInvoker)    = #PB_Checkbox_Checked
            SetGadgetState(#Check_RequireAdmin,    #PB_Checkbox_Unchecked)
          EndIf
          
        Case #Check_longPath
        Case #Check_DPIAware
        Case #Check_PerMonitor
        Case #Check_gdiscaling
          
        Case #Btn_Apply
          ManifestFlag = 0
          If GetGadgetState(#Check_RequireAdmin) : ManifestFlag + #DPI_RequireAdmin : EndIf
          If GetGadgetState(#Check_asInvoker)    : ManifestFlag + #DPI_asInvoker    : EndIf
          If GetGadgetState(#Check_longPath)     : ManifestFlag + #DPI_longPath     : EndIf
          If GetGadgetState(#Check_DPIAware)     : ManifestFlag + #DPI_Aware        : EndIf
          If GetGadgetState(#Check_PerMonitor)   : ManifestFlag + #DPI_PerMonitor   : EndIf
          If GetGadgetState(#Check_gdiscaling)   : ManifestFlag + #DPI_gdiScaling   : EndIf
                    
          If DPIawareManifest(FileName, ManifestFlag)
            DisableGadget(#Check_RequireAdmin, #True) : DisableGadget(#Check_asInvoker, #True) : DisableGadget(#Check_longPath, #True)
            DisableGadget(#Check_DPIAware, #True)     : DisableGadget(#Check_PerMonitor, #True) : DisableGadget(#Check_gdiscaling, #True)  : DisableGadget(#Btn_Apply, #True) : HideGadget(#Btn_Apply, #True) : HideGadget(#Txt_Done, #False)
            ;SetGadgetState(#Image_DPIAware, ImageID(#Valid_png)) : SetGadgetState(#Image_PerMonitor, ImageID(#Valid_png)) : SetGadgetState(#Image_gdiscaling, ImageID(#Valid_png))
            If GetGadgetState(#Check_RequireAdmin)    : SetGadgetState(#Image_RequireAdmin, ImageID(#Valid_png)) : Else : SetGadgetState(#Image_RequireAdmin, 0)   : EndIf
            If GetGadgetState(#Check_asInvoker)       : SetGadgetState(#Image_asInvoker, ImageID(#Valid_png))    : Else : SetGadgetState(#Image_asInvoker, 0)      : EndIf
            If GetGadgetState(#Check_longPath)        : SetGadgetState(#Image_longPath, ImageID(#Valid_png))     : Else : SetGadgetState(#Image_longPath, 0)       : EndIf
            If GetGadgetState(#Check_DPIAware)        : SetGadgetState(#Image_DPIAware, ImageID(#Valid_png))     : Else : SetGadgetState(#Image_DPIAware, 0)       : EndIf
            If GetGadgetState(#Check_PerMonitor)      : SetGadgetState(#Image_PerMonitor, ImageID(#Valid_png))   : Else : SetGadgetState(#Image_PerMonitor, 0)     : EndIf
            If GetGadgetState(#Check_gdiscaling)      : SetGadgetState(#Image_gdiscaling, ImageID(#Valid_png))   : Else : SetGadgetState(#Image_gdiscaling, 0)     : EndIf
          EndIf
          
      EndSelect
  EndSelect
ForEver
End

DataSection
  Valid_png:
  Data.q $0A1A0A0D474E5089,$524448490D000000,$1000000010000000,$FFF31F0000000608,$4752730100000061
  Data.q $0000E91CCEAE0042,$0000414D41670400,$00000561FC0B8FB1,$0000735948700900,$C701C30E0000C30E
  Data.q $49F401000064A86F,$7774634F38544144,$0720646464666777,$19A409819FFFFFFC,$002165062800C188
  Data.q $900F0F0F46063101,$01900481A641180B,$4ABEB92F91BBB12E,$04C5AFFC6064CCFF,$AE47A2E5F3562413
  Data.q $9FFA60655C7F655F,$31006C1AB995F2CA,$F254BC61FD737F9A,$2E402DFFCB3FF2A8,$3269AD6F6677F307
  Data.q $527C0972B6FF99CF,$4837E78D7822CEF9,$DE307E645FCD3621,$90296B68093E7C4A,$44CEBFA337F197FB
  Data.q $A12CAE6639200BD9,$FD697E2CFF04BF05,$1CBF8647C595FFC1,$9207FCE03DF22EFF,$A46E19FF8CFF8104
  Data.q $F02C0B37FA07EB3D,$CC056E4FAF52B18F,$9B5E1B46F78B6612,$C0C310C8C0CD7E7D,$7BFBA7FA4DFBE0C4
  Data.q $057DF2CF445B2F9D,$CDA05CA3F152E6B9,$5795BB0C0CD560B5,$817285627FB2E44A,$8E06068802C507DE
  Data.q $200E6C806B7FD03B,$32E801CD8AF1C6BE,$2CF900F6FFAC7FAD,$D6BE8B13F581FC40,$2D0018364067994C
  Data.q $9DF97EBD440F0FF8,$0C0C32C153197F8C,$5E6A06AD7EC43F5A,$CAE5003334836404,$D01800D800C33591
  Data.q $2852F4F4015F93EB,$0CFFACC0E5881ED7,$A1B307CF88579447,$24003140103DE400,$0B7CC804A591F6C8
  Data.q $F298BF4CBF830111,$4801007440719FB8,$3504C006E1102C1D,$0864173A01BF4B67,$EE493BA79C67FC04
  Data.q $55980419A2879432,$8210C50086405454,$1C4663012F79E7C2,$8A66B0DE399F3318,$0CD7471201FBE05C
  Data.q $360183E500BCF002,$40248133FEC43885,$C5D801439500640C,$1307015C2F001818,$4900000000150602
EndDataSection

Edit: Code updated with requireAdministrator, asInvoker, Long Path Aware and the scaling is now handled in the exemple app
Last edited by ChrisR on Fri Oct 15, 2021 3:11 pm, edited 9 times in total.
User avatar
Paul
PureBasic Expert
PureBasic Expert
Posts: 1108
Joined: Fri Apr 25, 2003 4:34 pm
Location: Canada
Contact:

Re: Update DPI Manifest in Executable

Post by Paul »

Why would you want to modify the manifest like this?
When an app is not DPI aware, Windows will auto scale the app to make everything the proper size when scaling is used. (things get blurry due to the scaling but everything is scaled properly)

Image

If the DPI flag is set in the manifest when the app is not actually DPI aware and scaling is not handled by the app, text will be clearer but sizing and coordinates are going to be very messed up.

Image


(screen shots on a 4k monitor with 175% scaling, Windows 10)
Image Image
User avatar
ChrisR
Enthusiast
Enthusiast
Posts: 409
Joined: Sun Jan 08, 2017 10:27 pm
Location: France

Re: Update Manifest in Executable

Post by ChrisR »

Hi Paul,
The main goal is to add the DPIaware Manifest, if needed, for example for old apps made blurry with windows automatic resizing:
Example below with ResHacker 3.6.0 which looks blurry here with a 175% zoom on windows 10.
It is better after adding DpiAware in the Manifest

Image


However, indeed, the example was not good with the DPI not handled, I updated the code on 1st post, it should be better now.
I also added, requireAdministrator and asInvoker, as options.

Image
User avatar
Paul
PureBasic Expert
PureBasic Expert
Posts: 1108
Joined: Fri Apr 25, 2003 4:34 pm
Location: Canada
Contact:

Re: Update Manifest in Executable

Post by Paul »

An app that is truly DPI aware would look the same size as a non DPI ware app that is auto scaled by Windows.
For example, this is your interface recreated and compiled as non DPI aware (left) and then DPI aware (right) on a 4k monitor at 175%.
Notice how everything is identical regardless of scaling.

Image

I'm just pointing out that setting the DPI aware flag in the manifest does not make an app DPI aware and the screen shot you posted clearly shows that simply setting the flag does not force things to scale properly.
Image Image
Rinzwind
Enthusiast
Enthusiast
Posts: 433
Joined: Wed Mar 11, 2009 4:06 pm
Location: NL

Re: Update Manifest in Executable

Post by Rinzwind »

Thanks for sharing. Nice technique and faster than hacking with resource hacker and yes, people who do this know the inherent risks. If only Windows managed it better and did not require dev involvement to make an app dpi aware (and frequently many changes are needed). MS changed their dpi ways multiple times since XP. A mess.
highend
User
User
Posts: 69
Joined: Tue Jun 17, 2014 4:49 pm

Re: Update Manifest in Executable

Post by highend »

For example, this is your interface recreated and compiled as non DPI aware (left) and then DPI aware (right) on a 4k monitor at 175%.
Could you post the code of this recreated interface please?
User avatar
ChrisR
Enthusiast
Enthusiast
Posts: 409
Joined: Sun Jan 08, 2017 10:27 pm
Location: France

Re: Update Manifest in Executable

Post by ChrisR »

Paul wrote: Fri Oct 15, 2021 2:09 am I'm just pointing out that setting the DPI aware flag in the manifest does not make an app DPI aware and the screen shot you posted clearly shows that simply setting the flag does not force things to scale properly.
Yes, I agree, but it can be still used for "some" old apps or for PerMonitorv2 with #WM_DPICHANGED!

highend wrote: Fri Oct 15, 2021 6:51 am
For example, this is your interface recreated and compiled as non DPI aware (left) and then DPI aware (right) on a 4k monitor at 175%.
Could you post the code of this recreated interface please?
I believe the interface is created with Enable DPI Aware Executable (Windows only) enabled
This option enable DPI awareness when creating an executable. That means than GUI created in PureBasic will scale automatically if the DPI of the screen is above 100%. Most of the process is seemless, but some case needs to be worked out, like pixel based gadgets (ImageGadget, CanvasGadget etc.).

The best solution to not have to manage it, like with the great Thunder93's [Module] DPI Awareness.

However, It would be really nice if the toolbar DPIaware was managed at compile time like other gadgets, with the Icon Button resized.
Same thing even for ImageGadget canvas, couldn't it be a function like GadgetDPIimageAware(#PB_ALL, #True))!
So that the scaling can be handled or not, at compile time.
Would it not be possible ? It's a pain otherwise for 4K screens as shown here in IDE and Icon bar on 4K monitor

I updated the code with 2 windows, one using the dpi ratio, the other using GadgetHeight(TmpGadget, #PB_Gadget_RequiredSize).
I didn't manage the DPI before, in my tools so it's quite new for me, I'm learning the DPI's pleasure :? step by step :)
Post Reply