AutoHotkey Community

It is currently May 26th, 2012, 1:33 am

All times are UTC [ DST ]




Post new topic Reply to topic  [ 35 posts ]  Go to page 1, 2, 3  Next
Author Message
PostPosted: December 21st, 2007, 6:14 pm 
Offline

Joined: April 22nd, 2007, 6:33 pm
Posts: 1833
This is just a quick demonstration to see if there's any interest in me continuing the function:

Image

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 March 22nd, 2008, 10:29 am, edited 15 times in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: December 21st, 2007, 7:49 pm 
Offline

Joined: July 20th, 2007, 10:23 am
Posts: 257
Location: Paris, France
Good idea :D
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? :lol:

Edited: you should also make a screenshot of the gui. It's always nice to have a visual example when dealing with guis.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: December 21st, 2007, 8:07 pm 
Offline

Joined: April 22nd, 2007, 6:33 pm
Posts: 1833
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 :?

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.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: December 21st, 2007, 8:18 pm 
Offline

Joined: July 20th, 2007, 10:23 am
Posts: 257
Location: Paris, France
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 :?
You're right. It was a bug I introduced myself (and corrected :)) 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! :D


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: December 21st, 2007, 8:28 pm 
Offline
User avatar

Joined: August 11th, 2004, 1:47 am
Posts: 5347
Location: UK
Great work! I would recommend you use the re: "i)<\s*(b|strong)\b[^>]*>(?'1'.+?)<\s*/\1\s*>".

_________________
GitHubScriptsIronAHK Contact by email not private message.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: December 21st, 2007, 8:30 pm 
Offline

Joined: April 22nd, 2007, 6:33 pm
Posts: 1833
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.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: December 22nd, 2007, 2:37 am 
Offline

Joined: April 22nd, 2007, 6:33 pm
Posts: 1833
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 December 22nd, 2007, 6:23 pm, edited 1 time in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: December 22nd, 2007, 6:00 pm 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
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.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: December 22nd, 2007, 6:21 pm 
Offline

Joined: April 22nd, 2007, 6:33 pm
Posts: 1833
Glad I got your seal of approval Lasz :)
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 :?

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!


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: December 22nd, 2007, 7:09 pm 
Offline

Joined: April 22nd, 2007, 6:33 pm
Posts: 1833
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 <


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: December 23rd, 2007, 12:19 am 
Offline

Joined: April 22nd, 2007, 6:33 pm
Posts: 1833
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.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: December 23rd, 2007, 1:12 am 
Offline

Joined: October 17th, 2006, 4:15 pm
Posts: 7501
Location: Australia
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.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: December 23rd, 2007, 4:51 am 
Offline

Joined: October 17th, 2006, 4:15 pm
Posts: 7501
Location: Australia
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. 8)
Image
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.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: December 23rd, 2007, 2:04 pm 
Offline

Joined: April 22nd, 2007, 6:33 pm
Posts: 1833
Thank you very much for the example Lex. As always your advice is 2nd to none :)

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 :? )

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

Image

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.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: December 23rd, 2007, 2:35 pm 
Offline

Joined: April 22nd, 2007, 6:33 pm
Posts: 1833
Or more complex things:

Image

by changing the variable html to:

http://www.autohotkey.net/~tic/html.txt


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 35 posts ]  Go to page 1, 2, 3  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: Stigg and 20 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group