AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

HTMLText 1.01 - Write HTML style text to a GUI
Goto page 1, 2, 3  Next
 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
tic



Joined: 22 Apr 2007
Posts: 1375

PostPosted: Fri Dec 21, 2007 5:14 pm    Post subject: HTMLText 1.01 - Write HTML style text to a GUI Reply with quote

This is just a quick demonstration to see if there's any interest in me continuing the function:



Code:
<fGeorgia><w100>Light text in Georgia</w></f><w1000>Heaviest text </w>Normal Text <u><i><b>This is underlined, italic and bold </b></i></u><cff0000><d>This is red and Deleted</d></c>


The idea is to allow html style coding to write text to a window, as it is very annoying having to write so many complex lines just to write a simple sentence that contains different colours, weights, sizes etc.

Usage:

Code:
HTMLText(x, y, Text, Gui)


x and y positions in the gui specified as the last parameter, and wrap text you wish to have tags with:

Colour: <cff0000></c>
Size: <s20></s> ; Not implemented.
Weight: <w400></w>
Bold: <b></b>
Italic: <i></i>
Delete/Strikeout: <d></d>
Underline: <u></u>
Font: <fArial></f>

Note:

- You must close tags in the order they were opened.
So, this is incorrect:
Code:
  <b><i>Bold+Italic</b></i>

This is correct:
Code:
  <b><i>Bold+Italic</i></b>


- you may not enclose a tag with the same tag.
ie
Code:
  <b>Here is <b>some</b> text</b>



Code:
; c = Colour
; s = Size
; w = Weight (max 1000)
; b = Bold
; i = Italic
; d = Delete/Strikeout
; u = Underline
; f = Font
#SingleInstance Force

Text = Normal <fImpact><w100>Light text </w></f><w1000>Heaviest text </w>Normal Text <u><i><b>This is underlined, italic and bold </b></i></u><cff0000><d>This is red and Deleted</d></c>

HTMLText(10, 10, Text, 2)
Gui, 2: Add, Text, x10 y+10, Not part of the function
Gui, 2: Show, AutoSize
Return

HTMLText(x, y, Text, Gui=1)
{
   AllText := Text
   Tags := "<c[0-9a-fA-F]+?>,<s[0-9]+?>,<w[0-9]+?>,<b>,<i>,<d>,<u>,<f.+?>"
   StringSplit, Tag, Tags, `,
   
   Loop
   {      
      Loop
      {      
         ;Gui, %Gui%: Font, s17
         
         FirstPos := ""
         Loop, %Tag0%
         {
            Pos := RegExMatch(Text, Tag%A_Index%, Test)
            If ((Pos) && (Pos < FirstPos)) || (!FirstPos)
            FirstPos := Pos
         }
         Pos := FirstPos               
         
         If (Pos) && (Pos != 1)
         {
            If !Started
            {
               Gui, %Gui%: Add, Text, x%x% y%y%, % SubStr(Text, 1, Pos-1)   ;%
               EndTrim += Pos-1
               StringTrimLeft, Text, Text, % Pos-1      ;%
               Started := 1
            }
            Else
            {
               Gui, %Gui%: Add, Text, x+0 yp+0, % SubStr(Text, 1, Pos-1)   ;%
               EndTrim += Pos-1
               StringTrimLeft, Text, Text, % Pos-1      ;%            
            }
         }
         Else If (Pos) && (Pos = 1)
         {      
            ETag := SubStr(Text, 2, 1)
            Pos := RegExMatch(Text, "<" ETag ".+?" ETag ">", Text, 1)
            If !Length
            {
               EndTrim += StrLen(Text)
               Length := 1
            }
            
            If ETag in b,i,d,u
            {
               StringReplace, Text, Text, <%ETag%>,, All
               StringReplace, Text, Text, </%ETag%>,, All
               If (Etag = "b")
               Gui, %Gui%: Font, Bold
               If (Etag = "i")
               Gui, %Gui%: Font, Italic
               If (Etag = "d")
               Gui, %Gui%: Font, Strike
               If (Etag = "u")
               Gui, %Gui%: Font, Underline
            }
            
            If ETag in c,w,f
            {
               Pos := RegExMatch(Text, "<" ETag "(.+?)>(.+?)</" ETag ">", Text, 1)
               If (Etag = "c")
               Gui, %Gui%: Font, c%Text1%
               If (Etag = "w")
               Gui, %Gui%: Font, w%Text1%
               If (Etag = "f")
               Gui, %Gui%: Font,, %Text1%

               Text := Text2
            }
                     
         }
         Else
         {
            If !Length
            EndTrim += StrLen(Text)
            If !Started
            {
               Gui, %Gui%: Add, Text, x%x% y%y%, %Text%
               Started := 1
            }
            Else
            Gui, %Gui%: Add, Text, x+0 yp+0, %Text%
            Length := ""
            Break
         }
      }
      Gui, %Gui%: Font
      
      StringTrimLeft, AllText, AllText, %EndTrim%
      Text := AllText
      Length := EndTrim := ""
      If !Text
      Break
   }   
}

Esc::ExitApp


Newer version:

Thought i may as well just update this code with the version I had last. There were still things to add, but I havent got round to doing it. The following code allows wrapping, but you cant specify a new line. Also using different sized text may make the texts appear at different heights as they could have different baselines. This is the same with using different fonts:

Code:
; c = Colour
; s = Size
; w = Weight (max 1000)
; b = Bold
; i = Italic
; d = Delete/Strikeout
; u = Underline
; f = Font

#SingleInstance Force
SetBatchLines -1

Text =
(
<ce5460f>Colour: </c><c7d1cba>This can be specified</c><c456745> using the c tag.</c>
<s14>Size: </s><s6>Different</s>sizes can be specified <s16>easily</s> using the s tag.
<w1000>Weight:</w><w100>Different</w>weights can be specified <w800>easily</w>using the w tag.
<b>Bold: </b>The b tag can be used for <b>bold</b>text.
<i>Italic: </i>The i tag can be used for <i>italic</i>text.
<d>Delete:</d> The d tag can be used for <d>deleted</d>text.
<u>Underline:</u> The u tag can be used for <u>underlined</u>text.
<fComic Sans MS>Font:</f>Different <fGaramond>fonts</f> can be specified with the f tag.
)

HTMLText("x10 y40 w400", Text, 2)
Gui, 2: Show, AutoSize
Return

;###########################################################################

HTMLText(Options, Text, Gui=1)
{   
   RestoreDHW := A_DetectHiddenWindows
   DetectHiddenWindows, On
   Gui, %Gui%: +LastFound
   hwnd := WinExist()
   Gui, %Gui%: Default
   
   RegExMatch(Options, "x([0-9]+)", x)
   RegExMatch(Options, "y([0-9]+)", y)
   RegExMatch(Options, "w([0-9]+)", w)
   x := x1, y := y1, w := w1
   
   StringReplace, Text, Text, `n,, All
   
   Loop
   {
      ControlGetPos, XPos, YPos, Width, Height, Static%A_Index%, ahk_id %hwnd%
      If !(Width || Height)
      {
         CN := A_Index-1
         Break
      }
   }   
   AllText := Text
   Tags := "<c[0-9a-fA-F]+?>,<s[0-9]+?>,<w[0-9]+?>,<b>,<i>,<d>,<u>,<f.+?>"
   StringSplit, Tag, Tags, `,
   
   Loop
   {     
      Loop
      {     
         FirstPos := ""
         Loop, %Tag0%
         {
            Pos := RegExMatch(Text, Tag%A_Index%, Test)
            If ((Pos) && (Pos < FirstPos)) || (!FirstPos)
            FirstPos := Pos
         }
         Pos := FirstPos               
         
         If (Pos) && (Pos != 1)
         {     
            IntText := SubStr(Text, 1, Pos-1)
            StringSplit, IntText, IntText, % " "   ;%           
            GoSub, AddText
            If !Length
            EndTrim += Pos-1
            StringTrimLeft, Text, Text, % Pos-1      ;%           
            Started := 1
         }
         Else If (Pos) && (Pos = 1)
         {     
            ETag := SubStr(Text, 2, 1)
            Pos := RegExMatch(Text, "<" ETag ".+?</" ETag ">", Text, 1)
            If !Length
            EndTrim += StrLen(Text)
         Length := 1
           
            If ETag in b,i,d,u
            {
               StringReplace, Text, Text, <%ETag%>,, All
               StringReplace, Text, Text, </%ETag%>,, All
               If (Etag = "b")
               Gui, %Gui%: Font, Bold
               If (Etag = "i")
               Gui, %Gui%: Font, Italic
               If (Etag = "d")
               Gui, %Gui%: Font, Strike
               If (Etag = "u")
               Gui, %Gui%: Font, Underline
            }
           
            If ETag in c,w,f,s
            {
               Pos := RegExMatch(Text, "<" ETag "(.+?)>(.+?)</" ETag ">", Text, 1)
               If (Etag = "c")
               Gui, %Gui%: Font, c%Text1%
               If (Etag = "w")
               Gui, %Gui%: Font, w%Text1%
               If (Etag = "f")
               Gui, %Gui%: Font,, %Text1%
               If (Etag = "s")
               Gui, %Gui%: Font, s%Text1%

               Text := Text2
            }                     
         }
         Else
         {     
            StringSplit, IntText, Text, % " "   ;%         
            If !Length
            EndTrim += StrLen(Text)
            GoSub, AddText         
            Started := 1
            Break
         }
      }
      Gui, %Gui%: Font
     
      StringTrimLeft, AllText, AllText, %EndTrim%
      Text := AllText
     Length := EndTrim := ""
      If !Text
      Break
   }
   DetectHiddenWindows, %RestoreDHW%
   Return, 0
   
   ;###########################################################################
   
   AddText:
   Loop, %IntText0%
   {
      CN++
     Gui, %Gui%: Add, Text, % ((A_Index = 1) && (!Started)) ? "x" x " y" y : "x+0 yp+0", % (A_Index != IntText0) ? IntText%A_Index% " " : IntText%A_Index%
      GuiControlGet, Pos, Pos, Static%CN%

      If (PosH != OldPosH) && (OldPosH)
      {
         NewY := OldPosY+OldPosH > PosY+PosH ? PosY+(OldPosH-PosH) : PosY-(PosH-OldPosH)

         GuiControl, Move, Static%CN%, % "y" NewY   ;%
         Gui, %Gui%: Add, Text, % "x" PosX+PosW " y" NewY " w" 0 " h" PosH   ;%
         CN++
      }
     
      OldPosX := PosX, OldPosY := PosY, OldPosW := PosW, OldPosH := PosH

      If (PosW+PosX > x+w) || (IntText%A_Index% = "<l>")
      {
         y += 40
         GuiControl, Move, Static%CN%, x%x% y%y%
         Gui, %Gui%: Add, Text, % "x" x+PosW " y" y " w" 0   ;%
         CN++
      }
   }
   Return
}

Esc::ExitApp


Last edited by tic on Sat Mar 22, 2008 9:29 am; edited 15 times in total
Back to top
View user's profile Send private message
Andreone



Joined: 20 Jul 2007
Posts: 257
Location: Paris, France

PostPosted: Fri Dec 21, 2007 6:49 pm    Post subject: Reply with quote

Good idea Very Happy
I just played with your code and I made few changes:
- adding ", isn't it?" add the end of your displayed sentence (your version lost the ?)
- the loop can be exited sooner
- If Pos are not needed
- IntermediateText := SubStr(Text, 1, (Pos ? Pos-1 : StrLen(Text))) is coded once

Code:
Text := "This text can have <b>bold</b> or non-<b>bold</b> text. It's <b>easy peasy!</b>, isn't it?"

HTMLText(10, 10, Text)
Gui, 1: Show, AutoSize
Return

HTMLText(x, y, Text, Gui=1)
{
   Loop
   {
      Gui, Font
      Pos := RegExMatch(Text, "<b>(.+?)</b>", Bold, 1)

      IntermediateText := SubStr(Text, 1, (Pos ? Pos-1 : StrLen(Text)))
      If IntermediateText
      {
         If !Started
         {
            Gui, %Gui%: Add, Text, x%x% y%y%, %IntermediateText%
            Started := 1
         }
         Else
         {
            Gui, %Gui%: Add, Text, x+0 yp+0, %IntermediateText%
         }
      }
   
      ; no more html text, quit loop now
      If !Pos
         Break
      
      Gui, Font, Bold
      If !Started
      {
         Gui, %Gui%: Add, Text, x%x% y%y%, % Bold1
         Started := 1
      }
      Else
         Gui, %Gui%: Add, Text, x+0 yp+0, % Bold1
   
      StringTrimLeft, Text, Text, % Pos+StrLen(Bold)-1
   }
}


But you put yourself into troubles: what about italic, underline, font size and font colors? Laughing

Edited: you should also make a screenshot of the gui. It's always nice to have a visual example when dealing with guis.
Back to top
View user's profile Send private message
tic



Joined: 22 Apr 2007
Posts: 1375

PostPosted: Fri Dec 21, 2007 7:07 pm    Post subject: Reply with quote

Code:
- IntermediateText := SubStr(Text, 1, (Pos ? Pos-1 : StrLen(Text))) is coded once


yes i would definitely do that, but it was just an example functionality, non optimised.

Quote:
- adding ", isn't it?" add the end of your displayed sentence (your version lost the ?)


it doesnt for me. it works fine Confused

Quote:
But you put yourself into troubles: what about italic, underline, font size and font colors?


Heh, yeh it will be troublesome, but doable i think. ill have to think about it if enough people are interested and then write it all up.
Back to top
View user's profile Send private message
Andreone



Joined: 20 Jul 2007
Posts: 257
Location: Paris, France

PostPosted: Fri Dec 21, 2007 7:18 pm    Post subject: Reply with quote

tic wrote:
Quote:
- adding ", isn't it?" add the end of your displayed sentence (your version lost the ?)
it doesnt for me. it works fine Confused
You're right. It was a bug I introduced myself (and corrected Smile) while I was tinkering your script.

Quote:
Heh, yeh it will be troublesome, but doable i think. ill have to think about it if enough people are interested and then write it all up.
You already have one vote! Very Happy
Back to top
View user's profile Send private message
Titan



Joined: 11 Aug 2004
Posts: 5390
Location: /b/

PostPosted: Fri Dec 21, 2007 7:28 pm    Post subject: Reply with quote

Great work! I would recommend you use the re: "i)<\s*(b|strong)\b[^>]*>(?'1'.+?)<\s*/\1\s*>".
_________________

Back to top
View user's profile Send private message Visit poster's website
tic



Joined: 22 Apr 2007
Posts: 1375

PostPosted: Fri Dec 21, 2007 7:30 pm    Post subject: Reply with quote

probably the best way i can think of to add all the other functionalities is to:

Take the first <

Then find what html code it is ie <b>

Then find the corresponding closing brace </b> along with all the text in between. ie:

Code:
<b><i>Italic+Bold</i>Just Bold</b>


Then take out the italic part:

Code:
<b><i>Italic+Bold</i></b>


and then the bold part:

Code:
<b>Just Bold</b>


and join them together.

Stringtrim all of that out and continue.

Its gonna be very hard, but im sure it can be done and will be very useful when finished.
Back to top
View user's profile Send private message
tic



Joined: 22 Apr 2007
Posts: 1375

PostPosted: Sat Dec 22, 2007 1:37 am    Post subject: Reply with quote

This code does not need optimising. I am still in the process of adding functionality and will leave optimisation until the end as it often hinders the readability of the code.

This has all the font properties added apart from setting size:

Code:
; c = Colour
; s = Size
; w = Weight (max 1000)
; b = Bold
; i = Italic
; d = Delete/Strikeout
; u = Underline
; f = Font
#SingleInstance Force

Text = <fGeorgia><w100>Light text in Georgia </w></f><w1000>Heaviest text </w>Normal Text <u><i><b>This is underlined, italic and bold </b></i></u><cff0000><d>This is red and Deleted</d></c>

HTMLText(10, 10, Text, 2)
Gui, 2: Add, Text, x10 y+10, Not part of the function
Gui, 2: Show, AutoSize
Return

HTMLText(x, y, Text, Gui=1)
{
   AllText := Text
   
   Loop
   {      
      Loop
      {      
         Pos := InStr(Text, "<")
         If (Pos) && (Pos != 1)
         {
            If !Started
            {
               Gui, %Gui%: Add, Text, x%x% y%y%, % SubStr(Text, 1, Pos-1)   ;%
               EndTrim += Pos-1
               StringTrimLeft, Text, Text, % Pos-1      ;%
               Started := 1
            }
            Else
            {
               Gui, %Gui%: Add, Text, x+0 yp+0, % SubStr(Text, 1, Pos-1)   ;%
               EndTrim += Pos-1
               StringTrimLeft, Text, Text, % Pos-1      ;%            
            }
         }
         Else If (Pos) && (Pos = 1)
         {      
            ETag := SubStr(Text, 2, 1)
            Pos := RegExMatch(Text, "<" ETag ".+?" ETag ">", Text, 1)
            If !Length
            {
               EndTrim += StrLen(Text)
               Length := 1
            }
            
            If ETag in b,i,d,u
            {
               StringReplace, Text, Text, <%ETag%>,, All
               StringReplace, Text, Text, </%ETag%>,, All
               If (Etag = "b")
               Gui, %Gui%: Font, Bold
               If (Etag = "i")
               Gui, %Gui%: Font, Italic
               If (Etag = "d")
               Gui, %Gui%: Font, Strike
               If (Etag = "u")
               Gui, %Gui%: Font, Underline
            }
            
            If ETag in c,w,f
            {
               Pos := RegExMatch(Text, "<" ETag "(.+?)>(.+?)</" ETag ">", Text, 1)
               If (Etag = "c")
               Gui, %Gui%: Font, c%Text1%
               If (Etag = "w")
               Gui, %Gui%: Font, w%Text1%
               If (Etag = "f")
               Gui, %Gui%: Font,, %Text1%

               Text := Text2
            }
                     
         }
         Else
         {
            If !Length
            EndTrim += StrLen(Text)
            If !Started
            {
               Gui, %Gui%: Add, Text, x%x% y%y%, %Text%
               Started := 1
            }
            Else
            Gui, %Gui%: Add, Text, x+0 yp+0, %Text%
            Length := ""
            Break
         }
      }
      Gui, %Gui%: Font
      
      StringTrimLeft, AllText, AllText, %EndTrim%
      Text := AllText
      Length := EndTrim := ""
      If !Text
      Break
   }   
}

Esc::ExitApp


A note is that you may not use the < or > symbol currently and also you must strictly follow html style coding patterns. ie you cannot do:

Code:
<i><b>hello</i></b>


You must close tags in the order they were opened:

Code:
<i><b>hello</b></i>


I will add the ability to specify a width and text will be wrapped accordingly, and will also add the ability to specify font and size. There may be many bugs and that is why i have not updated this to the top post. Please inform me of all of them.

Enjoy


Last edited by tic on Sat Dec 22, 2007 5:23 pm; edited 1 time in total
Back to top
View user's profile Send private message
Laszlo



Joined: 14 Feb 2005
Posts: 4078
Location: Pittsburgh

PostPosted: Sat Dec 22, 2007 5:00 pm    Post subject: Reply with quote

Very useful!
I’d also had use of super/subscripts, if possible. They are useful in describing algorithms, adding footnotes, etc. If we had fractions, long sqrt signs (covering a whole expression) professional looking help screens could be popped up, without using richedit or IE controls.
Back to top
View user's profile Send private message
tic



Joined: 22 Apr 2007
Posts: 1375

PostPosted: Sat Dec 22, 2007 5:21 pm    Post subject: Reply with quote

Glad I got your seal of approval Lasz Smile
Quote:

professional looking help screens could be popped up, without using richedit or IE controls.


I completely agree. I think it looks "tacky" using richedit/ie... controls as it doesnt look flush with the gui. It just looks stuck on.

I have found myself several times writing a credits gui or something similar in my programs, ie Amun, and found it more than annoying to switch continually between bold, italic and normal text, and that doesnt even include all the other styles im not using.

I am just adding in now the ability to use < and > without it destroying the persons script, and then will move on to the user being able to specify a width for the control, which might prove troublesome Confused

The problem is that i would need to know the width of the next word before it was created! If I knew afterwards then I could wrap back round, but this would be inaccurate, as the previous word would have already exceeded its allocated width. The only way I can think to properly do this, (and i probably wont use this method though) is to actually create the whole thing first, read all the widths, and then create it again, once knowing the calculated widths

As you can see any help with ideas will be very helpful!
Back to top
View user's profile Send private message
tic



Joined: 22 Apr 2007
Posts: 1375

PostPosted: Sat Dec 22, 2007 6:09 pm    Post subject: Reply with quote

Using < and > no longer ruins coding, and can be used as long as they do not have the letter c,s,w,b,i,d,u,f directly to the right of a <
Back to top
View user's profile Send private message
tic



Joined: 22 Apr 2007
Posts: 1375

PostPosted: Sat Dec 22, 2007 11:19 pm    Post subject: Reply with quote

I dont have any idea how to get the heights and widths of the text before its added, so I didnt want to do this, but may have to.....

does anyone know how to find the 1st gui that doesnt exist.

ie... My program is already using Gui, 1 through to Gui, 5

So I want to find what is the 1st number of a gui thats not being used, so i want to find the number 6.

Any ideas?

Edit:

Or is there a way to create a gui (like you would normally Gui, 99:Add, text) except that it wouldnt intefere with any exisitng guis, so basically can a gui be created that isnt gui 1-99 but is something else?

It just needs to be created and then immediately destroyed, without even showing it.
Back to top
View user's profile Send private message
Lexikos



Joined: 17 Oct 2006
Posts: 2739
Location: Australia, Qld

PostPosted: Sun Dec 23, 2007 12:12 am    Post subject: Reply with quote

tic wrote:
So I want to find what is the 1st number of a gui thats not being used, so i want to find the number 6.

Code:
Loop, 99
{
    Gui, %A_Index%:+LastFoundExist
    ifWinNotExist
    {
        N := A_Index
        break
    }
}
Msgbox %N%

Quote:
Unlike other options, LastFoundExist is recognized only when no other options appear on the same line. +LastFoundExist is the same as +LastFound except that the window is not created if it does not already exist. The main use for this is to detect whether a particular GUI window exists.
Back to top
View user's profile Send private message
Lexikos



Joined: 17 Oct 2006
Posts: 2739
Location: Australia, Qld

PostPosted: Sun Dec 23, 2007 3:51 am    Post subject: Reply with quote

tic wrote:
I think it looks "tacky" using richedit/ie... controls as it doesnt look flush with the gui. It just looks stuck on.

I disagree. Cool

Uses two IE controls (GuiAddHtml) and a Text control. The second IE control has text and an image.

Code:
GuiAddHtml(html, Options="") ; (only positioning options should be used)
{
    IE_Init()
    Gui, +LastFound
   
    if ! RegExMatch(Options, "(?<!\S)W(\d+)", w)
        w1 := 100
   
    ie := IE_Add(WinExist(), 0, 0, w1, 100)
    WinSet, ExStyle, -0x200, % "ahk_id " COM_AtlAxGetContainer(ie)

    IE_LoadURL(ie, "about:blank")
    doc := IE_Document(ie)
    COM_Invoke(doc, "write", html)
    COM_Invoke(doc, "close")
   
    body := COM_Invoke(doc, "body")
   
    if !(w && RegExMatch(Options, "(?<!\S)H\d+"))
    {
        ; Wait up to one second for document to load, in case images were specified.
        Loop 10 {
            if COM_Invoke(doc, "readyState") = "complete"
                break
            Sleep, 100
        }

        ; body.offsetHeight seems to simply be the height of the control,
        ; so use the bottom of the lowest element.
        h := 0
        all := COM_Invoke(body, "all")
        Loop % COM_Invoke(all, "length") {
            item := COM_Invoke(all, "item", A_Index-1)
            x := COM_Invoke(item, "clientLeft") + COM_Invoke(item, "offsetLeft")
                + COM_Invoke(item, "offsetWidth")
            y := COM_Invoke(item, "clientTop") + COM_Invoke(item, "offsetTop")
                + COM_Invoke(item, "offsetHeight")
            if (y > h)
                h := y
            if (x > w1)
                w1 := x
            COM_Release(item)
        }
        COM_Release(all)
    }
   
    COM_Release(body)
    COM_Release(doc)
   
    Gui, Add, Text, W%w1% H%h% %Options% hwndhtext Hidden, guihtml%ie%
    GuiControlGet, t, Pos, guihtml%ie%
    IE_Move(ie, tX, tY, tW, tH)
   
    return ie
}

The default width is 100, though it will be expanded automatically if necessary. Height is calculated automatically (if not specified), and a hidden Text control is added to allow the next added control to be positioned automatically.

Example usage:
Code:
; Get COLOR_3DFACE (default GUI colour.)
SetFormat, Integer, H
bgc := DllCall("GetSysColor","int",15)
bgc := bgc >> 16 | bgc & 0xFF00 | (bgc & 0xFF) << 16
bgc := SubStr("000000" SubStr(bgc, 3), -5)
SetFormat, Integer, D

html =
(
<body bgcolor="#%bgc%" scroll="no" style="margin: 0">
... html content ...<br>
</body>
)

GuiAddHtml(html, "W135")

Gui, Show

The <br> is necessary (in the example) because the auto-sizing code only considers elements descended from body (i.e. not raw text directly contained by the body element.)

Edit: I forgot to mention - GuiAddHtml requires IE.ahk and COM.ahk.
Back to top
View user's profile Send private message
tic



Joined: 22 Apr 2007
Posts: 1375

PostPosted: Sun Dec 23, 2007 1:04 pm    Post subject: Reply with quote

Thank you very much for the example Lex. As always your advice is 2nd to none Smile

Very cool. It seems a tiny bit slow to complete, but I think thats fine.

Here is the full code for anyone that wants to try it (I know people hate me taking functions out of the standard library etc... but I just cant help it. I hate to include all that code when its not needed Confused )

I would like to wrap all this into 1 easy to use function and add some of my own options. As long as no-one has any objections Id like to neaten this and supercede my function with this



Code:
; Get COLOR_3DFACE (default GUI colour.)
SetFormat, Integer, H
bgc := DllCall("GetSysColor","int",15)
bgc := bgc >> 16 | bgc & 0xFF00 | (bgc & 0xFF) << 16
bgc := SubStr("000000" SubStr(bgc, 3), -5)
SetFormat, Integer, D

html =
(
<body bgcolor="#%bgc%" scroll="no" style="margin: 0">
<html>
<body>

<b>This text is bold</b>

<br>

<strong>
This text is strong
</strong>

<br>

<big>
This text is big
</big>

<br>

<em>
This text is emphasized
</em>

<br>

<i>
This text is italic
</i>

<br>

<small>
This text is small
</small>

<br>

This text contains
<sub>
subscript
</sub>

<br>

This text contains
<sup>
superscript
</sup>

</body>
</html><br>
</body>
)

GuiAddHtml(html, "W200")

Gui, Show
Return


GuiAddHtml(html, Options="") ; (only positioning options should be used)
{
    IE_Init()
    Gui, +LastFound
   
    if ! RegExMatch(Options, "(?<!\S)W(\d+)", w)
        w1 := 100
   
    ie := IE_Add(WinExist(), 0, 0, w1, 100)
    WinSet, ExStyle, -0x200, % "ahk_id " COM_AtlAxGetContainer(ie)

    IE_LoadURL(ie, "about:blank")
    doc := IE_Document(ie)
    COM_Invoke(doc, "write", html)
    COM_Invoke(doc, "close")
   
    body := COM_Invoke(doc, "body")
   
    if !(w && RegExMatch(Options, "(?<!\S)H\d+"))
    {
        ; Wait up to one second for document to load, in case images were specified.
        ; Loop 10 {
            ; if COM_Invoke(doc, "readyState") = "complete"
                ; break
            ; Sleep, 100
        ; }

        ; body.offsetHeight seems to simply be the height of the control,
        ; so use the bottom of the lowest element.
        h := 0
        all := COM_Invoke(body, "all")
        Loop % COM_Invoke(all, "length") {
            item := COM_Invoke(all, "item", A_Index-1)
            x := COM_Invoke(item, "clientLeft") + COM_Invoke(item, "offsetLeft")
                + COM_Invoke(item, "offsetWidth")
            y := COM_Invoke(item, "clientTop") + COM_Invoke(item, "offsetTop")
                + COM_Invoke(item, "offsetHeight")
            if (y > h)
                h := y
            if (x > w1)
                w1 := x
            COM_Release(item)
        }
        COM_Release(all)
    }
   
    COM_Release(body)
    COM_Release(doc)
   
    Gui, Add, Text, W%w1% H%h% %Options% hwndhtext Hidden, guihtml%ie%
    GuiControlGet, t, Pos, guihtml%ie%
    IE_Move(ie, tX, tY, tW, tH)
   
    return ie
}

Esc::ExitApp

IE_Init()
{
   COM_AtlAxWinInit()
}

COM_AtlAxWinInit(Version = "")
{
   COM_CoInitialize()
   If Not   DllCall("GetModuleHandle", "str", "atl" . Version)
      DllCall("LoadLibrary"    , "str", "atl" . Version)
   Return   DllCall("atl" . Version . "\AtlAxWinInit")
}

COM_CoInitialize()
{
   Return   DllCall("ole32\CoInitialize", "Uint", 0)
}

IE_Add(hWnd, x, y, w, h)
{
   Return   COM_AtlAxGetControl(COM_AtlAxCreateContainer(hWnd, x, y, w, h, "Shell.Explorer"))
}

COM_AtlAxCreateContainer(hWnd, l, t, w, h, Name = "", Version = "")
{
   Return   DllCall("CreateWindowEx", "Uint",0x200, "str", "AtlAxWin" . Version, "Uint", Name ? &Name : 0, "Uint", 0x54000000, "int", l, "int", t, "int", w, "int", h, "Uint", hWnd, "Uint", 0, "Uint", 0, "Uint", 0)
}

COM_AtlAxGetControl(hWnd, Version = "")
{
   If   DllCall("atl" . Version . "\AtlAxGetControl", "Uint", hWnd, "UintP", punk)=0
      pdsp:=COM_QueryInterface(punk), COM_Release(punk)
   Return   pdsp
}

COM_QueryInterface(ppv, IID = "")
{
   If   DllCall(NumGet(NumGet(1*ppv)+0), "Uint", ppv, "Uint", COM_GUID4String(IID,IID ? IID : IID=0 ? "{00000000-0000-0000-C000-000000000046}" : "{00020400-0000-0000-C000-000000000046}"), "UintP", ppv)=0
   Return   ppv
}

COM_GUID4String(ByRef CLSID, String)
{
   VarSetCapacity(CLSID, 16)
   DllCall("ole32\CLSIDFromString", "Uint", COM_Unicode4Ansi(String,String,38), "Uint", &CLSID)
   Return   &CLSID
}

COM_Unicode4Ansi(ByRef wString, sString, nSize = "")
{
   If (nSize = "")
       nSize:=DllCall("kernel32\MultiByteToWideChar", "Uint", 0, "Uint", 0, "Uint", &sString, "int", -1, "Uint", 0, "int", 0)
   VarSetCapacity(wString, nSize * 2 + 1)
   DllCall("kernel32\MultiByteToWideChar", "Uint", 0, "Uint", 0, "Uint", &sString, "int", -1, "Uint", &wString, "int", nSize + 1)
   Return   &wString
}

COM_AtlAxGetContainer(pdsp)
{
   DllCall(NumGet(NumGet(1*pdsp)+ 0), "Uint", pdsp, "Uint", COM_GUID4String(IID_IOleWindow,"{00000114-0000-0000-C000-000000000046}"), "UintP", pwin)
   DllCall(NumGet(NumGet(1*pwin)+12), "Uint", pwin, "UintP", hCtrl)
   DllCall(NumGet(NumGet(1*pwin)+ 8), "Uint", pwin)
   Return   DllCall("GetParent", "Uint", hCtrl)
}

IE_LoadURL(pwb, u)
{
   pUrl := COM_SysAllocString(u)
   VarSetCapacity(var, 8 * 2, 0)
   DllCall(NumGet(NumGet(1*pwb)+44), "Uint", pwb, "Uint", pUrl, "Uint", &var, "Uint", &var, "Uint", &var, "Uint", &var)
   COM_SysFreeString(pUrl)
}

COM_SysFreeString(bstr)
{
   Return   DllCall("oleaut32\SysFreeString", "Uint", bstr)
}

COM_SysAllocString(sString)
{
   Return   DllCall("oleaut32\SysAllocString", "Uint", COM_Ansi2Unicode(sString,wString))
}

COM_Ansi2Unicode(ByRef sString, ByRef wString, nSize = "")
{
   If (nSize = "")
       nSize:=DllCall("kernel32\MultiByteToWideChar", "Uint", 0, "Uint", 0, "Uint", &sString, "int", -1, "Uint", 0, "int", 0)
   VarSetCapacity(wString, nSize * 2 + 1)
   DllCall("kernel32\MultiByteToWideChar", "Uint", 0, "Uint", 0, "Uint", &sString, "int", -1, "Uint", &wString, "int", nSize + 1)
   Return   &wString
}

IE_Document(pwb)
{
   DllCall(NumGet(NumGet(1*pwb)+72), "Uint", pwb, "UintP", pdoc)
   Return   pdoc
}

COM_Invoke(pdisp, sName, arg0="vT_NoNe",arg1="vT_NoNe",arg2="vT_NoNe",arg3="vT_NoNe",arg4="vT_NoNe",arg5="vT_NoNe",arg6="vT_NoNe",arg7="vT_NoNe",arg8="vT_NoNe",arg9="vT_NoNe")
{
   Global   _hResult_
   sParams   := 0123456789
   Loop,   Parse,   sParams
      If   (arg%A_LoopField% == "vT_NoNe")
      {
         nParams := A_Index - 1
         Break
      }
   sParams   := SubStr(sParams,1,nParams)
   VarSetCapacity(DispParams,16,0), VarSetCapacity(varResult,16,0), VarSetCapacity(IID_NULL,16,0), VarSetCapacity(varg,nParams*16,0)
      NumPut(&varg,DispParams,0), NumPut(nParams,DispParams,8)
   If   (nFlags := SubStr(sName,0) <> "=" ? 3 : 12) = 12
      NumPut(&varResult,DispParams,4), NumPut(1,DispParams,12), NumPut(-3,varResult), sName:=SubStr(sName,1,-1)
   Loop,    Parse,   sParams
      If   arg%A_LoopField% Is Not Integer
               NumPut(8,varg,(nParams-A_Index)*16,"Ushort"), NumPut(COM_SysAllocString(arg%A_LoopField%),varg,(nParams-A_Index)*16+8)
      Else   NumPut(SubStr(arg%A_LoopField%,1,1)="+" ? 9 : 3,varg,(nParams-A_Index)*16,"Ushort"), NumPut(arg%A_LoopField%,varg,(nParams-A_Index)*16+8)
   If (0 =   _hResult_:=DllCall(NumGet(NumGet(1*pdisp)+20), "Uint", pdisp, "Uint", &IID_NULL, "UintP", COM_Unicode4Ansi(wName, sName), "Uint", 1, "Uint", LCID, "intP", dispID))
   && (0 =   _hResult_:=DllCall(NumGet(NumGet(1*pdisp)+24), "Uint", pdisp, "int", dispID, "Uint", &IID_NULL, "Uint", LCID, "Ushort", nFlags, "Uint", &dispParams, "Uint", &varResult, "Uint", 0, "Uint", 0))
   && (3 =   nFlags)
      Result:=(vt:=NumGet(varResult,0,"Ushort"))=8||vt<0x1000&&DllCall("oleaut32\VariantChangeTypeEx","Uint",&varResult,"Uint",&varResult,"Uint",LCID,"Ushort",1,"Ushort",8)=0 ? COM_Ansi4Unicode(bstr:=NumGet(varResult,8)) . SubStr(COM_SysFreeString(bstr),1,0) : NumGet(varResult,8)
   Loop, %   nParams
      NumGet(varg,(A_Index-1)*16,"Ushort")=8 ? COM_SysFreeString(NumGet(varg,(A_Index-1)*16+8)) : ""
   Return   Result
}

COM_Ansi4Unicode(pString, nSize = "")
{
   If (nSize = "")
       nSize:=DllCall("kernel32\WideCharToMultiByte", "Uint", 0, "Uint", 0, "Uint", pString, "int", -1, "Uint", 0, "int",  0, "Uint", 0, "Uint", 0)
   VarSetCapacity(sString, nSize)
   DllCall("kernel32\WideCharToMultiByte", "Uint", 0, "Uint", 0, "Uint", pString, "int", -1, "str", sString, "int", nSize + 1, "Uint", 0, "Uint", 0)
   Return   sString
}

COM_Release(ppv)
{
   Return   DllCall(NumGet(NumGet(1*ppv)+8), "Uint", ppv)
}

IE_Move(pwb, l, t, w, h)
{
   WinMove, % "ahk_id " . COM_AtlAxGetContainer(pwb), , l, t, w, h
}


I had actually nearly finished writing a way to wrap the old version without having to use a new gui. I would add all the text in a straight line, and after each new piece of text was added, then it would check the x position that it was added and its width and then determine whther to guicontrol it to the next line and continue from there, which i actually think was a quite neat way to do it.
Back to top
View user's profile Send private message
tic



Joined: 22 Apr 2007
Posts: 1375

PostPosted: Sun Dec 23, 2007 1:35 pm    Post subject: Reply with quote

Or more complex things:



by changing the variable html to:

http://www.autohotkey.net/~tic/html.txt
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Goto page 1, 2, 3  Next
Page 1 of 3

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group