1

Тема: AHK: Бегущая строка

Написал что в голову пришло:


info := "Бегущая строка"    
str := "              " info "              "
Gui, Color, 696969
Gui, Font, s44 cffffff
Gui, Add, Text, vText +0x1000, 00000000000000
Gui, Show 
StrLen := StrLen(str) , I := 0 

    Loop 
    {
        If (I = 0) 
            GuiControl, +Right, Text 
        Else If (I = 13) 
            GuiControl, +Left, Text 
        GuiControl,, Text, % SubStr(str, ++I, 14) 
        If (I = StrLen)
            I := 0 
        Sleep 100
    }
    Return 
    
GuiClose:
    ExitApp

и более ничего не приходило
У кого какие идеи как это сделать "поровнее", и желательно с попиксельным смещением строки?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.30.01 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

2

Re: AHK: Бегущая строка

Если на скорую руку, то так:

Gui, Color, Gray
Gui, Add, Text, hwndhText 0x1000 x20 y20 w350 h50
Gui, Show, w390 h90

Gui, 2:+Parent%hText% -Caption
Gui, 2:Color, 606060
Gui, 2:Font, s24 cFFAA00
Gui, 2:Add, Text, vInfo x350 y6, Следующая станция "Международная".
Gui, 2:Show, x0 y0

Loop
{
    Sleep, 20
    GuiControl, 2:MoveDraw, Info, % "x" 350 - mod(A_Index*2, 900)
    Sleep, 10   ; так вроде меньше мелькает
}
return

GuiClose:
    ExitApp

Но некоторого мелькания, скорее всего, избежать не удастся. По-хорошему, такие вещи через GDI нужно делать.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

3

Re: AHK: Бегущая строка

teadrinker
Как всегда гениально! Вот крутилось оно на уме... со вторым гуи.
Не пойму почему тут

mod(A_Index*2, 900)

именно 900?
Ещё строка не заканчиваясь слева до конца пропадает, и начинается снова...

teadrinker пишет:

По-хорошему, такие вещи через GDI нужно делать.

И пока вроде ещё никто не делал.
Я знаю вы в GDI дока.
Хотелось бы увидеть ваше решение.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.30.01 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

4

Re: AHK: Бегущая строка

serzh82saratov пишет:

Не пойму почему тут ... именно 900?
Ещё строка не заканчиваясь слева до конца пропадает, и начинается снова...

900 — это 350 + примерная длина строки. У меня как раз хватает, у тебя, видимо, из за другого разрешения экрана нужно поменять на большее. На форуме где-то был код, определяющий размер текста.
Через GDI:

SetBatchLines, -1

Text = Следующая станция "Международная".
SleepDuration = 8  ; при уменьшении скорость возрастёт
Font = Arial
Size := 24
Margin := 11   ; отступ от верхнего края строки

DllCall("Winmm\timeBeginPeriod", UInt, 3)
OnExit, Exit

Gui, Color, Gray
Gui, Add, Text, hwndhText x20 y20 w350 h50
Gui, Show, w390 h90

pToken := Startup()

hbm := CreateDIBSection(350, 50)
hdc := DllCall("CreateCompatibleDC", "ptr", 0, "ptr")
obm := DllCall("SelectObject", "ptr", hdc, "ptr", hbm, "ptr")
DllCall("gdiplus\GdipCreateFromHDC", "ptr", hdc, "ptr*", G)
DllCall("gdiplus\GdipSetSmoothingMode", "ptr", G, "int", 4)

pFillBrush := Gdip_BrushCreateSolid(0xff606060)
hTextDC := GetDC(hText)

Loop
{
   DllCall("gdiplus\GdipFillRectangle", "ptr", G, "ptr", pFillBrush
      , "float", 0, "float", 0, "float", 350, "float", 50)

   Options := "x" 350 - mod(A_Index, w) " y" Margin " cFFFFAA00 r4 s" Size
   w := RegExReplace(Gdip_TextToGraphics(G, Text, Options, Font, w, 50), "(.*?\|){2}(.*?)(\.\d+)?\|.*", "$2") + 350

   BitBlt(hTextDC, -1, -1, 350, 50, hdc, 0, 0)
   DllCall("Sleep", UInt, SleepDuration)
}
return

GuiClose:
   ExitApp

Exit:
   DllCall("Winmm\timeEndPeriod", UInt, 3)
   Gdip_DeleteBrush(pFillBrush)
   DllCall("SelectObject", "ptr", hdc, "ptr", obm, "ptr"), DllCall("DeleteObject", "ptr", hbm)
   DeleteDC(hdc), ReleaseDC(hTextDC)
   DllCall("gdiplus\GdipDeleteGraphics", "ptr", G), Gdip_Shutdown(pToken)
   ExitApp
   
Startup()
{
   if !DllCall("GetModuleHandle", "str", "gdiplus", "ptr")
      DllCall("LoadLibrary", "str", "gdiplus")
   VarSetCapacity(si, A_PtrSize = 8 ? 24 : 16, 0), si := Chr(1)
   DllCall("gdiplus\GdiplusStartup", "uptr*", pToken, "ptr", &si, "ptr", 0)
   return pToken
}

Gdip_Shutdown(pToken)
{
   DllCall("gdiplus\GdiplusShutdown", "uptr", pToken)
   if hModule := DllCall("GetModuleHandle", "str", "gdiplus", "ptr")
      DllCall("FreeLibrary", "ptr", hModule)
   return 0
}

CreateDIBSection(w, h, hdc="", bpp=32, ByRef ppvBits=0)
{
   hdc2 := hdc ? hdc : GetDC()
   VarSetCapacity(bi, 40, 0)
   NumPut(w, bi, 4, "uint"), NumPut(h, bi, 8, "uint"), NumPut(40, bi, 0, "uint"), NumPut(1, bi, 12, "ushort"), NumPut(0, bi, 16), NumPut(bpp, bi, 14, "ushort")
   hbm := DllCall("CreateDIBSection", "ptr" , hdc2, "ptr" , &bi, "uint" , 0, "ptr*", ppvBits, "ptr" , 0, "uint" , 0, "ptr")

   if !hdc
      ReleaseDC(hdc2)
   return hbm
}

Gdip_TextToGraphics(pGraphics, Text, Options, Font="Arial", Width="", Height="", Measure=0)
{
   IWidth := Width, IHeight:= Height
   
   RegExMatch(Options, "i)X([\-\d\.]+)(p*)", xpos)
   RegExMatch(Options, "i)Y([\-\d\.]+)(p*)", ypos)
   RegExMatch(Options, "i)W([\-\d\.]+)(p*)", Width)
   RegExMatch(Options, "i)H([\-\d\.]+)(p*)", Height)
   RegExMatch(Options, "i)C(?!(entre|enter))([a-f\d]+)", Colour)
   RegExMatch(Options, "i)Top|Up|Bottom|Down|vCentre|vCenter", vPos)
   RegExMatch(Options, "i)NoWrap", NoWrap)
   RegExMatch(Options, "i)R(\d)", Rendering)
   RegExMatch(Options, "i)S(\d+)(p*)", Size)

   if !Gdip_DeleteBrush(Gdip_CloneBrush(Colour2))
      PassBrush := 1, pBrush := Colour2
   
   if !(IWidth && IHeight) && (xpos2 || ypos2 || Width2 || Height2 || Size2)
      return -1

   Style := 0, Styles := "Regular|Bold|Italic|BoldItalic|Underline|Strikeout"
   Loop, Parse, Styles, |
   {
      if RegExMatch(Options, "\b" A_loopField)
      Style |= (A_LoopField != "StrikeOut") ? (A_Index-1) : 8
   }
  
   Align := 0, Alignments := "Near|Left|Centre|Center|Far|Right"
   Loop, Parse, Alignments, |
   {
      if RegExMatch(Options, "\b" A_loopField)
         Align |= A_Index//2.1      ; 0|0|1|1|2|2
   }

   xpos := (xpos1 != "") ? xpos2 ? IWidth*(xpos1/100) : xpos1 : 0
   ypos := (ypos1 != "") ? ypos2 ? IHeight*(ypos1/100) : ypos1 : 0
   Width := Width1 ? Width2 ? IWidth*(Width1/100) : Width1 : IWidth
   Height := Height1 ? Height2 ? IHeight*(Height1/100) : Height1 : IHeight
   if !PassBrush
      Colour := "0x" (Colour2 ? Colour2 : "ff000000")
   Rendering := ((Rendering1 >= 0) && (Rendering1 <= 5)) ? Rendering1 : 4
   Size := (Size1 > 0) ? Size2 ? IHeight*(Size1/100) : Size1 : 12

   hFamily := Gdip_FontFamilyCreate(Font)
   hFont := Gdip_FontCreate(hFamily, Size, Style)
   FormatStyle := NoWrap ? 0x4000 | 0x1000 : 0x4000
   hFormat := Gdip_StringFormatCreate(FormatStyle)
   pBrush := PassBrush ? pBrush : Gdip_BrushCreateSolid(Colour)
   if !(hFamily && hFont && hFormat && pBrush && pGraphics)
      return !pGraphics ? -2 : !hFamily ? -3 : !hFont ? -4 : !hFormat ? -5 : !pBrush ? -6 : 0
   
   CreateRectF(RC, xpos, ypos, Width, Height)
   Gdip_SetStringFormatAlign(hFormat, Align)
   Gdip_SetTextRenderingHint(pGraphics, Rendering)
   ReturnRC := Gdip_MeasureString(pGraphics, Text, hFont, hFormat, RC)

   if vPos
   {
      StringSplit, ReturnRC, ReturnRC, |
      
      if (vPos = "vCentre") || (vPos = "vCenter")
         ypos += (Height-ReturnRC4)//2
      else if (vPos = "Top") || (vPos = "Up")
         ypos := 0
      else if (vPos = "Bottom") || (vPos = "Down")
         ypos := Height-ReturnRC4
      
      CreateRectF(RC, xpos, ypos, Width, ReturnRC4)
      ReturnRC := Gdip_MeasureString(pGraphics, Text, hFont, hFormat, RC)
   }

   if !Measure
      E := Gdip_DrawString(pGraphics, Text, hFont, hFormat, pBrush, RC)

   if !PassBrush
      Gdip_DeleteBrush(pBrush)
   Gdip_DeleteStringFormat(hFormat)   
   Gdip_DeleteFont(hFont)
   Gdip_DeleteFontFamily(hFamily)
   return E ? E : ReturnRC
}

Gdip_DeleteBrush(pBrush)
{
   return DllCall("gdiplus\GdipDeleteBrush", "ptr", pBrush)
}

Gdip_CloneBrush(pBrush)
{
   DllCall("gdiplus\GdipCloneBrush", "ptr", pBrush, "ptr*", pBrushClone)
   return pBrushClone
}

Gdip_FontFamilyCreate(Font)
{
   DllCall("gdiplus\GdipCreateFontFamilyFromName", "wstr", Font, "ptr", 0, "ptr*", hFamily)
   return hFamily
}

Gdip_FontCreate(hFamily, Size, Style=0)
{
   DllCall("gdiplus\GdipCreateFont", "ptr", hFamily, "float", Size, "int", Style, "int", 0, "ptr*", hFont)
   return hFont
}

Gdip_DeleteGraphics(pGraphics)
{
   return DllCall("gdiplus\GdipDeleteGraphics", "ptr", pGraphics)
}

Gdip_StringFormatCreate(Format=0, Lang=0)
{
   DllCall("gdiplus\GdipCreateStringFormat", "int", Format, "int", Lang, "ptr*", hFormat)
   return hFormat
}

Gdip_BrushCreateSolid(ARGB=0xff000000)
{
   DllCall("gdiplus\GdipCreateSolidFill", "uint", ARGB, "ptr*", pBrush)
   return pBrush
}

CreateRectF(ByRef RectF, x, y, w, h)
{
   VarSetCapacity(RectF, 16)
   NumPut(x, RectF, 0, "float"), NumPut(y, RectF, 4, "float"), NumPut(w, RectF, 8, "float"), NumPut(h, RectF, 12, "float")
}

Gdip_SetStringFormatAlign(hFormat, Align)
{
   return DllCall("gdiplus\GdipSetStringFormatAlign", "ptr", hFormat, "int", Align)
}

Gdip_SetTextRenderingHint(pGraphics, RenderingHint)
{
   return DllCall("gdiplus\GdipSetTextRenderingHint", "ptr", pGraphics, "int", RenderingHint)
}

Gdip_MeasureString(pGraphics, sString, hFont, hFormat, ByRef RectF)
{
   VarSetCapacity(RC, 16)
   DllCall("gdiplus\GdipMeasureString", "ptr", pGraphics
      , "wstr", sString, "int", -1, "ptr", hFont, "ptr", &RectF, "ptr", hFormat, "ptr", &RC, "uint*", Chars, "uint*", Lines)
   return &RC ? NumGet(RC, 0, "float") "|" NumGet(RC, 4, "float") "|" NumGet(RC, 8, "float") "|" NumGet(RC, 12, "float") "|" Chars "|" Lines : 0
}

Gdip_DrawString(pGraphics, sString, hFont, hFormat, pBrush, ByRef RectF)
{
   return DllCall("gdiplus\GdipDrawString", "ptr", pGraphics
      , "wstr", sString, "int", -1, "ptr", hFont, "ptr", &RectF, "ptr", hFormat, "ptr", pBrush)
}

Gdip_DeleteStringFormat(hFormat)
{
   return DllCall("gdiplus\GdipDeleteStringFormat", "ptr", hFormat)
}

Gdip_DeleteFont(hFont)
{
   return DllCall("gdiplus\GdipDeleteFont", "ptr", hFont)
}

Gdip_DeleteFontFamily(hFamily)
{
   return DllCall("gdiplus\GdipDeleteFontFamily", "ptr", hFamily)
}

BitBlt(ddc, dx, dy, dw, dh, sdc, sx, sy, Raster="")
{
   return DllCall("gdi32\BitBlt", "ptr", dDC, "int", dx, "int", dy, "int", dw, "int", dh
   , "ptr", sDC, "int", sx, "int", sy, "uint", Raster ? Raster : 0x00CC0020)
}

DeleteDC(hdc)
{
   return DllCall("DeleteDC", "ptr", hdc)
}

GetDC(hwnd=0)
{
   return DllCall("GetDC", "ptr", hwnd, "ptr")
}

ReleaseDC(hdc, hwnd=0)
{
   return DllCall("ReleaseDC", "ptr", hwnd, "ptr", hdc)
}

Длина строки должна автоматически считаться.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

5

Re: AHK: Бегущая строка

Большое спасибо!
Буду курить. Но немножко мелькает у меня, но конечно меньше

На форуме где-то был код, определяющий размер текста.

Что то про тултип кажется.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.30.01 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

6

Re: AHK: Бегущая строка

Чтобы совсем было идеально, нужно делать в layered window, как в примерах к GDI+. Но в них нельзя стандартные контролы вставлять, и они не могут быть дочерними.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

7

Re: AHK: Бегущая строка

А вот удалось слоёное в обычное вставить:

SetBatchLines, -1
global hGuiBack, hGuiString, hdc, XDiff, YDiff, XGuiString, YGuiString

Text = Следующая станция "Международная".
SleepDuration = 8  ; при уменьшении скорость возрастёт
Font = Arial
Size := 24
Margin := 11   ; отступ от верхнего края строки

DllCall("Winmm\timeBeginPeriod", UInt, 3)
OnExit, Exit

Gui, Back:+hwndhGuiBack
Gui, Back:Color, Gray
Gui, Back:Show, w390 h90

Gui, -Caption +E0x80020 +OwnerBack +ToolWindow +hwndhGuiString
Gui, Show, NA

OnMessage(0x46, "WM_WINDOWPOSCHANGING")

pToken := Startup()

hbm := CreateDIBSection(350, 50)
hdc := DllCall("CreateCompatibleDC", Ptr, 0, Ptr)
obm := DllCall("SelectObject", Ptr, hdc, Ptr, hbm, Ptr)
DllCall("gdiplus\GdipCreateFromHDC", Ptr, hdc, PtrP, G)
DllCall("gdiplus\GdipSetSmoothingMode", Ptr, G, Int, 4)

VarSetCapacity(WI, 60), NumPut(60, WI, "UInt")
DllCall("GetWindowInfo", Ptr, hGuiBack, Ptr, &WI)
XGui := NumGet(WI, 4, "UInt"), YGui := NumGet(WI, 8, "UInt")
XClient := NumGet(WI, 20, "UInt"), YClient := NumGet(WI, 24, "UInt")
XDiff := XClient - XGui, YDiff := YClient - YGui

XGuiString := XClient + 20
YGuiString := YClient + 20

Loop
{
   DllCall("gdiplus\GdipGraphicsClear", Ptr, G, UInt, 0xff606060)

   Options := "x" 350 - mod(A_Index, w ? w : 10000) " y" Margin " cFFFFAA00 r4 s" Size
   RC := TextToGraphics(G, Text, Options, Font, w ? w : 10000, 50)
   w := RegExReplace(RC, "(.*?\|){2}(.*?)(\.\d+)?\|.*", "$2") + 350

   UpdateLayeredWindow(hGuiString, hdc, XGuiString, YGuiString, 350, 50)
   
   DllCall("Sleep", UInt, SleepDuration)
}
return

BackGuiClose:
   ExitApp

Exit:
   DllCall("Winmm\timeEndPeriod", UInt, 3)
   DllCall("SelectObject", Ptr, hdc, Ptr, obm, Ptr), DllCall("DeleteObject", Ptr, hbm)
   DeleteDC(hdc), DllCall("gdiplus\GdipDeleteGraphics", Ptr, G), Shutdown(pToken)
   ExitApp
   
WM_WINDOWPOSCHANGING(wp, lp, msg, hwnd)
{
   x := NumGet(lp+0, A_PtrSize*2, "UInt"), y := NumGet(lp+0, A_PtrSize*2+4, "UInt")
   if (x = 0 && y = 0)
      return
   UpdateLayeredWindow(hGuiString, hdc, XGuiString := x + XDiff + 20, YGuiString := y + YDiff + 20, 350, 50)
}
   
Startup()
{
   if !DllCall("GetModuleHandle", Str, "gdiplus", Ptr)
      DllCall("LoadLibrary", Str, "gdiplus")
   VarSetCapacity(si, A_PtrSize = 8 ? 24 : 16, 0), si := Chr(1)
   DllCall("gdiplus\GdiplusStartup", UPtrP, pToken, Ptr, &si, Ptr, 0)
   return pToken
}

Shutdown(pToken)
{
   DllCall("gdiplus\GdiplusShutdown", UPtr, pToken)
   if hModule := DllCall("GetModuleHandle", Str, "gdiplus", Ptr)
      DllCall("FreeLibrary", Ptr, hModule)
   return 0
}

CreateDIBSection(w, h, hdc="", bpp=32, ByRef ppvBits=0)
{
   hdc2 := hdc ? hdc : GetDC()
   VarSetCapacity(bi, 40, 0)
   NumPut(w, bi, 4, "UInt"), NumPut(h, bi, 8, "UInt"), NumPut(40, bi, 0, "UInt"), NumPut(1, bi, 12, "ushort"), NumPut(0, bi, 16), NumPut(bpp, bi, 14, "ushort")
   hbm := DllCall("CreateDIBSection", Ptr , hdc2, Ptr , &bi, UInt , 0, PtrP, ppvBits, Ptr , 0, UInt , 0, Ptr)

   if !hdc
      ReleaseDC(hdc2)
   return hbm
}

TextToGraphics(pGraphics, Text, Options, Font="Arial", Width="", Height="", Measure=0)
{
   IWidth := Width, IHeight:= Height
   
   RegExMatch(Options, "i)X([\-\d\.]+)(p*)", xpos)
   RegExMatch(Options, "i)Y([\-\d\.]+)(p*)", ypos)
   RegExMatch(Options, "i)W([\-\d\.]+)(p*)", Width)
   RegExMatch(Options, "i)H([\-\d\.]+)(p*)", Height)
   RegExMatch(Options, "i)C(?!(entre|enter))([a-f\d]+)", Colour)
   RegExMatch(Options, "i)Top|Up|Bottom|Down|vCentre|vCenter", vPos)
   RegExMatch(Options, "i)NoWrap", NoWrap)
   RegExMatch(Options, "i)R(\d)", Rendering)
   RegExMatch(Options, "i)S(\d+)(p*)", Size)

   if !DeleteBrush(CloneBrush(Colour2))
      PassBrush := 1, pBrush := Colour2
   
   if !(IWidth && IHeight) && (xpos2 || ypos2 || Width2 || Height2 || Size2)
      return -1

   Style := 0, Styles := "Regular|Bold|Italic|BoldItalic|Underline|Strikeout"
   Loop, Parse, Styles, |
   {
      if RegExMatch(Options, "\b" A_loopField)
      Style |= (A_LoopField != "StrikeOut") ? (A_Index-1) : 8
   }
  
   Align := 0, Alignments := "Near|Left|Centre|Center|Far|Right"
   Loop, Parse, Alignments, |
   {
      if RegExMatch(Options, "\b" A_loopField)
         Align |= A_Index//2.1      ; 0|0|1|1|2|2
   }

   xpos := (xpos1 != "") ? xpos2 ? IWidth*(xpos1/100) : xpos1 : 0
   ypos := (ypos1 != "") ? ypos2 ? IHeight*(ypos1/100) : ypos1 : 0
   Width := Width1 ? Width2 ? IWidth*(Width1/100) : Width1 : IWidth
   Height := Height1 ? Height2 ? IHeight*(Height1/100) : Height1 : IHeight
   if !PassBrush
      Colour := "0x" (Colour2 ? Colour2 : "ff000000")
   Rendering := ((Rendering1 >= 0) && (Rendering1 <= 5)) ? Rendering1 : 4
   Size := (Size1 > 0) ? Size2 ? IHeight*(Size1/100) : Size1 : 12

   hFamily := FontFamilyCreate(Font)
   hFont := FontCreate(hFamily, Size, Style)
   FormatStyle := NoWrap ? 0x4000 | 0x1000 : 0x4000
   hFormat := StringFormatCreate(FormatStyle)
   pBrush := PassBrush ? pBrush : BrushCreateSolid(Colour)
   if !(hFamily && hFont && hFormat && pBrush && pGraphics)
      return !pGraphics ? -2 : !hFamily ? -3 : !hFont ? -4 : !hFormat ? -5 : !pBrush ? -6 : 0
   
   CreateRectF(RC, xpos, ypos, Width, Height)
   SetStringFormatAlign(hFormat, Align)
   SetTextRenderingHint(pGraphics, Rendering)
   ReturnRC := MeasureString(pGraphics, Text, hFont, hFormat, RC)

   if vPos
   {
      StringSplit, ReturnRC, ReturnRC, |
      
      if (vPos = "vCentre") || (vPos = "vCenter")
         ypos += (Height-ReturnRC4)//2
      else if (vPos = "Top") || (vPos = "Up")
         ypos := 0
      else if (vPos = "Bottom") || (vPos = "Down")
         ypos := Height-ReturnRC4
      
      CreateRectF(RC, xpos, ypos, Width, ReturnRC4)
      ReturnRC := MeasureString(pGraphics, Text, hFont, hFormat, RC)
   }

   if !Measure
      E := DrawString(pGraphics, Text, hFont, hFormat, pBrush, RC)

   if !PassBrush
      DeleteBrush(pBrush)
   DeleteStringFormat(hFormat)   
   DeleteFont(hFont)
   DeleteFontFamily(hFamily)
   return E ? E : ReturnRC
}

DeleteBrush(pBrush)
{
   return DllCall("gdiplus\GdipDeleteBrush", Ptr, pBrush)
}

CloneBrush(pBrush)
{
   DllCall("gdiplus\GdipCloneBrush", Ptr, pBrush, PtrP, pBrushClone)
   return pBrushClone
}

FontFamilyCreate(Font)
{
   DllCall("gdiplus\GdipCreateFontFamilyFromName", WStr, Font, Ptr, 0, PtrP, hFamily)
   return hFamily
}

FontCreate(hFamily, Size, Style=0)
{
   DllCall("gdiplus\GdipCreateFont", Ptr, hFamily, Float, Size, Int, Style, Int, 0, PtrP, hFont)
   return hFont
}

DeleteGraphics(pGraphics)
{
   return DllCall("gdiplus\GdipDeleteGraphics", Ptr, pGraphics)
}

StringFormatCreate(Format=0, Lang=0)
{
   DllCall("gdiplus\GdipCreateStringFormat", Int, Format, Int, Lang, PtrP, hFormat)
   return hFormat
}

BrushCreateSolid(ARGB=0xff000000)
{
   DllCall("gdiplus\GdipCreateSolidFill", UInt, ARGB, PtrP, pBrush)
   return pBrush
}

CreateRectF(ByRef RectF, x, y, w, h)
{
   VarSetCapacity(RectF, 16)
   NumPut(x, RectF, 0, "float"), NumPut(y, RectF, 4, "float"), NumPut(w, RectF, 8, "float"), NumPut(h, RectF, 12, "float")
}

SetStringFormatAlign(hFormat, Align)
{
   return DllCall("gdiplus\GdipSetStringFormatAlign", Ptr, hFormat, Int, Align)
}

SetTextRenderingHint(pGraphics, RenderingHint)
{
   return DllCall("gdiplus\GdipSetTextRenderingHint", Ptr, pGraphics, Int, RenderingHint)
}

MeasureString(pGraphics, sString, hFont, hFormat, ByRef RectF)
{
   VarSetCapacity(RC, 16)
   DllCall("gdiplus\GdipMeasureString", Ptr, pGraphics
      , WStr, sString, Int, -1, Ptr, hFont, Ptr, &RectF, Ptr, hFormat, Ptr, &RC, UIntP, Chars, UIntP, Lines)
   return &RC ? NumGet(RC, 0, "float") "|" NumGet(RC, 4, "float") "|" NumGet(RC, 8, "float") "|" NumGet(RC, 12, "float") "|" Chars "|" Lines : 0
}

DrawString(pGraphics, sString, hFont, hFormat, pBrush, ByRef RectF)
{
   return DllCall("gdiplus\GdipDrawString", Ptr, pGraphics
      , WStr, sString, Int, -1, Ptr, hFont, Ptr, &RectF, Ptr, hFormat, Ptr, pBrush)
}

DeleteStringFormat(hFormat)
{
   return DllCall("gdiplus\GdipDeleteStringFormat", Ptr, hFormat)
}

DeleteFont(hFont)
{
   return DllCall("gdiplus\GdipDeleteFont", Ptr, hFont)
}

DeleteFontFamily(hFamily)
{
   return DllCall("gdiplus\GdipDeleteFontFamily", Ptr, hFamily)
}

DeleteDC(hdc)
{
   return DllCall("DeleteDC", Ptr, hdc)
}

GetDC(hwnd=0)
{
   return DllCall("GetDC", Ptr, hwnd, Ptr)
}

ReleaseDC(hdc, hwnd=0)
{
   return DllCall("ReleaseDC", Ptr, hwnd, Ptr, hdc)
}

UpdateLayeredWindow(hwnd, hdc, x="", y="", w="", h="", Alpha=255)
{
   if ((x != "") && (y != ""))
      VarSetCapacity(pt, 8), NumPut(x, pt, 0, "UInt"), NumPut(y, pt, 4, "UInt")

   if (w = "") ||(h = "")
      WinGetPos,,, w, h, ahk_id %hwnd%
   
   return DllCall("UpdateLayeredWindow", Ptr, hwnd, Ptr, 0, Ptr, ((x = "") && (y = "")) ? 0 : &pt
   , Int64P, w|h<<32, Ptr, hdc, Int64P, 0, UInt, 0, UIntP, Alpha<<16|1<<24, UInt, 2)
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

8 (изменено: serzh82saratov, 2013-08-12 13:12:44)

Re: AHK: Бегущая строка

Спасибо за пример, отлично работает!
Я так понял, что все функции взяты в оригинальном виде из GDI?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.30.01 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

9 (изменено: serzh82saratov, 2013-08-12 13:46:59)

Re: AHK: Бегущая строка

Кстати если двигать не текст, а всё окно то не мелькает:


Gui, Color, Gray
Gui, Add, Progress, hwndhControl Border Background606060 x20 y20 w350 h50  
Gui, Show, w390 h90

Gui, 2:+Parent%hControl% -Caption +Lastfound
Gui, 2:Color, 606060
Gui, 2:Font, s24 cFFAA00
Gui, 2:Add, Text, x350 y6, Следующая станция "Международная".
Gui, 2:Show, x0 y0
WinGetPos, , , Width 

Loop
{ 
    Gui, 2:Show, % "Na y0 x" I := I < -Width ? 0 : I - 1 
    Sleep 1  
}
return

И тут тоже спасибо. Я узнал что можно родительским делать не только окно, а ещё и контролы.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.30.01 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

10

Re: AHK: Бегущая строка

serzh82saratov пишет:

Я так понял, что все функции взяты в оригинальном виде из GDI?

Взяты оттуда, но изменены для поддержки 64-битного интерпретатора.

serzh82saratov пишет:

Кстати если двигать не текст, а всё окно то не мелькает

Да, хорошее решение, у меня тоже не мелькает. Чуть-чуть подёргивается

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

11 (изменено: serzh82saratov, 2013-09-29 18:52:53)

Re: AHK: Бегущая строка

Ещё один способ:


Gui, Color, Gray 
Gui -DPIScale +AlwaysOnTop +Disabled
Gui, margin, 20, 20 
Gui, Add, ActiveX, w590 h90 vIE, shell explorer
IE.Navigate("about:blank")

html =
(  
<html>   
<center>
<body bgcolor=#606060> 
<font size="12" color="FFAA00" face="Arial">
<marquee scrollamount="10" "> 
Следующая станция "Международная".
</marquee>
</font> 
</body>
</center>
</html> 
)
IE.Document.Write(html) 
Gui, show  
Return
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.30.01 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

12

Re: AHK: Бегущая строка

Так совсем глючно.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

13 (изменено: serzh82saratov, 2013-10-02 21:54:08)

Re: AHK: Бегущая строка

Так немного получше


width= 350 
height= 60 
fontsize= 50
ChrColor=FFAA00
 
html =
(           
  <style>
   marquee {
    position: absolute; /* Абсолютное позиционирование */
    right: 0px; /* Положение элемента от правого края */
    left: 0px; /* Положение элемента от правого края */
    top: 0px; /* Положение от верхнего края */
    width: %width%px; /* Ширина блока */ 
    background: #606060; /* Цвет фона */  
    color: "%ChrColor%"`;
    font-size: "%fontsize%"`; 
   } 
  </style>
   
 <body scroll="no" topmargin="0" leftmargin="0" onselectstart="return false"  oncontextmenu="return false">  
  <marquee bgcolor="#606060" color="%ChrColor%" width="%width%" height="%height%" truespeed scrollamount="1" scrolldelay="7" >  
   Следующая станция "Международная".  
  </marquee> 
 </body>  
)
 
OnExit HTMLGuiClose
Gui, HTML: Color, Gray 
Gui HTML: -DPIScale +AlwaysOnTop 
Gui, HTML: margin, 20, 20 
Gui, HTML: Add, ActiveX, w%width% h%height% vIE, HTMLFile 
Gui, HTML: show   
IE.Write(html)  
return 
 
HTMLGuiClose:
    IE := "" 
    ExitApp 

Ну это я предложил как "короткий" вариант.

И как способ без цикла, который нельзя прерывать.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.30.01 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

14

Re: AHK: Бегущая строка

teadrinker
В этом посте у тебя как то хитро задаётся фон для текста через GdipGraphicsClear. Но я никак не пойму как в твоём примере сделать фон текста прозрачным.
Сделал свой вариант со сдвигом Bitmap текста поверх другого Bitmap с фоном, но оказалось очень прожорливо для процессора.


Loop
{
	If (XPos < -WText)
		XPos := W + 1
	Else
		XPos -= 1
	Gdip_DrawImage(GDest, pBmpBckg, 0, 0, W, H, 0, 0, W, H)
	Gdip_DrawImage(GDest, pBmpText, XPos, Margin, WText, HText, 0, 0, WText, HText)
	hBmpDest := Gdip_CreateHBITMAPFromBitmap(pBmpDest, 0x00000000)
	SelectObject(hDCDest, hBmpDest)
	DeleteObject(hBmpDest)
	UpdateLayeredWindow(hGui, hDCDest, X, Y, W, H)
	DllCall("Sleep", UInt, 2)
}

Не привожу весь код, для запуска его надо перепиливать, но тут думаю это не потребуется, так как вряд ли выше может находиться что то влияющее на производительность..

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.30.01 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

15

Re: AHK: Бегущая строка

DllCall("gdiplus\GdipGraphicsClear", Ptr, G, UInt, 0x0)

Так?

16

Re: AHK: Бегущая строка

Так я пробовал. У вас качество шрифта не ухудшается?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.30.01 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

17 (изменено: teadrinker, 2019-03-02 22:40:50)

Re: AHK: Бегущая строка

Правильно, а потом вырезать из основного окна фон через WinSet, Region. У меня не ухудшается вроде.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

18

Re: AHK: Бегущая строка

https://i.imgur.com/T0JGh7e.png
https://i.imgur.com/0SjKGNI.png
Про WinSet, Region не понял.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.30.01 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

19

Re: AHK: Бегущая строка

serzh82saratov, у меня - нет.
https://imgur.com/a/I6dRiUb
Попробуйте так:


Loop
{
   DllCall("gdiplus\GdipGraphicsClear", Ptr, G, UInt, 0x0)

   Options := "x" 350 - mod(A_Index, w ? w : 10000) " y" Margin " cFFFFAA00 r4 s" Size
   DllCall("gdiplus\GdipSetTextRenderingHint", "Ptr", G, "int", 4)
   RC := TextToGraphics(G, Text, Options, Font, w ? w : 10000, 50)
   w := RegExReplace(RC, "(.*?\|){2}(.*?)(\.\d+)?\|.*", "$2") + 350

   UpdateLayeredWindow(hGuiString, hdc, XGuiString, YGuiString, 350, 50)
   DllCall("Sleep", UInt, SleepDuration)
}

20

Re: AHK: Бегущая строка

Прошу прощения, скопировал заново код, не портит.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.30.01 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

21

Re: AHK: Бегущая строка

serzh82saratov пишет:

Про WinSet, Region не понял.

Я подумал, ты хочешь сделать насквозь прозрачный фон.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

22

Re: AHK: Бегущая строка

Нет, хочу подложить свой Bitmap, но это ещё тоже надо подумать. Тут ведь hdc полностью обновляется, и самое простое Bitmap отображать в GuiBack?
И если бы надо было текст двигать вместе с фоном, например сделав текстуру фона из картинки, как это лучше провернуть?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.30.01 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

23

Re: AHK: Бегущая строка

Если фон менять не нужно, подложить картинку в основное окно, если двигать с фоном, тогда наверно подрисовывать фон после GdipGraphicsClear с тем же сдвигом, что и текст.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

24

Re: AHK: Бегущая строка

Размер шрифта сильно влияет на производительность.


#SingleInstance Force
#Persistent  
#NoEnv
SetBatchLines -1
ListLines Off


global hGuiBack, hGuiString, hdc, XDiff, YDiff, XGuiString, YGuiString

Text = Следующая станция "Международная".
SleepDuration = 4  ; при уменьшении скорость возрастёт
Font = Arial
Size := 700
Margin := 0   ; отступ от верхнего края строки

W := 1600
H := 900

DllCall("Winmm\timeBeginPeriod", UInt, 3)
OnExit, Exit

Gui, Back:+hwndhGuiBack
Gui, Back:Color, Gray
Gui, Back:Margin, 0, 0
Gui, Back:Add, Pic, w%W% h%H%, Pic1.jpg
Gui, Back:Show, w%W% h%H%

Gui, -Caption +E0x80020 +OwnerBack +ToolWindow +hwndhGuiString
Gui, Show, NA

OnMessage(0x46, "WM_WINDOWPOSCHANGING")

pToken := Startup()

hbm := CreateDIBSection(W, H)
hdc := DllCall("CreateCompatibleDC", Ptr, 0, Ptr)
obm := DllCall("SelectObject", Ptr, hdc, Ptr, hbm, Ptr)
DllCall("gdiplus\GdipCreateFromHDC", Ptr, hdc, PtrP, G)
DllCall("gdiplus\GdipSetSmoothingMode", Ptr, G, Int, 4)

VarSetCapacity(WI, 60), NumPut(60, WI, "UInt")
DllCall("GetWindowInfo", Ptr, hGuiBack, Ptr, &WI)
XGui := NumGet(WI, 4, "UInt"), YGui := NumGet(WI, 8, "UInt")
XClient := NumGet(WI, 20, "UInt"), YClient := NumGet(WI, 24, "UInt")
XDiff := XClient - XGui, YDiff := YClient - YGui

XGuiString := XClient 
YGuiString := YClient 

Loop
{
   DllCall("gdiplus\GdipGraphicsClear", Ptr, G, UInt, 0)

   Options := "x" W - mod(A_Index, wt ? wt : 100000) " y" Margin " cFFFFAA00 r4 s" Size
   RC := TextToGraphics(G, Text, Options, Font, wt ? wt : 100000, H)
   wt := RegExReplace(RC, "(.*?\|){2}(.*?)(\.\d+)?\|.*", "$2") + W

   UpdateLayeredWindow(hGuiString, hdc, XGuiString, YGuiString, W, H)
   
   DllCall("Sleep", UInt, SleepDuration)
}
return

~Esc::
GuiEscape: 
	ExitApp 
	
BackGuiClose:
   ExitApp

Exit:
   DllCall("Winmm\timeEndPeriod", UInt, 3)
   DllCall("SelectObject", Ptr, hdc, Ptr, obm, Ptr), DllCall("DeleteObject", Ptr, hbm)
   DeleteDC(hdc), DllCall("gdiplus\GdipDeleteGraphics", Ptr, G), Shutdown(pToken)
   ExitApp
   
WM_WINDOWPOSCHANGING(wp, lp, msg, hwnd)
{
   x := NumGet(lp+0, A_PtrSize*2, "UInt"), y := NumGet(lp+0, A_PtrSize*2+4, "UInt")
   if (x = 0 && y = 0)
      return
   UpdateLayeredWindow(hGuiString, hdc, XGuiString := x + XDiff + 20, YGuiString := y + YDiff + 20, 350, 50)
}
   
Startup()
{
   if !DllCall("GetModuleHandle", Str, "gdiplus", Ptr)
      DllCall("LoadLibrary", Str, "gdiplus")
   VarSetCapacity(si, A_PtrSize = 8 ? 24 : 16, 0), si := Chr(1)
   DllCall("gdiplus\GdiplusStartup", UPtrP, pToken, Ptr, &si, Ptr, 0)
   return pToken
}

Shutdown(pToken)
{
   DllCall("gdiplus\GdiplusShutdown", UPtr, pToken)
   if hModule := DllCall("GetModuleHandle", Str, "gdiplus", Ptr)
      DllCall("FreeLibrary", Ptr, hModule)
   return 0
}

CreateDIBSection(w, h, hdc="", bpp=32, ByRef ppvBits=0)
{
   hdc2 := hdc ? hdc : GetDC()
   VarSetCapacity(bi, 40, 0)
   NumPut(w, bi, 4, "UInt"), NumPut(h, bi, 8, "UInt"), NumPut(40, bi, 0, "UInt"), NumPut(1, bi, 12, "ushort"), NumPut(0, bi, 16), NumPut(bpp, bi, 14, "ushort")
   hbm := DllCall("CreateDIBSection", Ptr , hdc2, Ptr , &bi, UInt , 0, PtrP, ppvBits, Ptr , 0, UInt , 0, Ptr)

   if !hdc
      ReleaseDC(hdc2)
   return hbm
}

TextToGraphics(pGraphics, Text, Options, Font="Arial", Width="", Height="", Measure=0)
{
   IWidth := Width, IHeight:= Height
   
   RegExMatch(Options, "i)X([\-\d\.]+)(p*)", xpos)
   RegExMatch(Options, "i)Y([\-\d\.]+)(p*)", ypos)
   RegExMatch(Options, "i)W([\-\d\.]+)(p*)", Width)
   RegExMatch(Options, "i)H([\-\d\.]+)(p*)", Height)
   RegExMatch(Options, "i)C(?!(entre|enter))([a-f\d]+)", Colour)
   RegExMatch(Options, "i)Top|Up|Bottom|Down|vCentre|vCenter", vPos)
   RegExMatch(Options, "i)NoWrap", NoWrap)
   RegExMatch(Options, "i)R(\d)", Rendering)
   RegExMatch(Options, "i)S(\d+)(p*)", Size)

   if !DeleteBrush(CloneBrush(Colour2))
      PassBrush := 1, pBrush := Colour2
   
   if !(IWidth && IHeight) && (xpos2 || ypos2 || Width2 || Height2 || Size2)
      return -1

   Style := 0, Styles := "Regular|Bold|Italic|BoldItalic|Underline|Strikeout"
   Loop, Parse, Styles, |
   {
      if RegExMatch(Options, "\b" A_loopField)
      Style |= (A_LoopField != "StrikeOut") ? (A_Index-1) : 8
   }
  
   Align := 0, Alignments := "Near|Left|Centre|Center|Far|Right"
   Loop, Parse, Alignments, |
   {
      if RegExMatch(Options, "\b" A_loopField)
         Align |= A_Index//2.1      ; 0|0|1|1|2|2
   }

   xpos := (xpos1 != "") ? xpos2 ? IWidth*(xpos1/100) : xpos1 : 0
   ypos := (ypos1 != "") ? ypos2 ? IHeight*(ypos1/100) : ypos1 : 0
   Width := Width1 ? Width2 ? IWidth*(Width1/100) : Width1 : IWidth
   Height := Height1 ? Height2 ? IHeight*(Height1/100) : Height1 : IHeight
   if !PassBrush
      Colour := "0x" (Colour2 ? Colour2 : "ff000000")
   Rendering := ((Rendering1 >= 0) && (Rendering1 <= 5)) ? Rendering1 : 4
   Size := (Size1 > 0) ? Size2 ? IHeight*(Size1/100) : Size1 : 12

   hFamily := FontFamilyCreate(Font)
   hFont := FontCreate(hFamily, Size, Style)
   FormatStyle := NoWrap ? 0x4000 | 0x1000 : 0x4000
   hFormat := StringFormatCreate(FormatStyle)
   pBrush := PassBrush ? pBrush : BrushCreateSolid(Colour)
   if !(hFamily && hFont && hFormat && pBrush && pGraphics)
      return !pGraphics ? -2 : !hFamily ? -3 : !hFont ? -4 : !hFormat ? -5 : !pBrush ? -6 : 0
   
   CreateRectF(RC, xpos, ypos, Width, Height)
   SetStringFormatAlign(hFormat, Align)
   SetTextRenderingHint(pGraphics, Rendering)
   ReturnRC := MeasureString(pGraphics, Text, hFont, hFormat, RC)

   if vPos
   {
      StringSplit, ReturnRC, ReturnRC, |
      
      if (vPos = "vCentre") || (vPos = "vCenter")
         ypos += (Height-ReturnRC4)//2
      else if (vPos = "Top") || (vPos = "Up")
         ypos := 0
      else if (vPos = "Bottom") || (vPos = "Down")
         ypos := Height-ReturnRC4
      
      CreateRectF(RC, xpos, ypos, Width, ReturnRC4)
      ReturnRC := MeasureString(pGraphics, Text, hFont, hFormat, RC)
   }

   if !Measure
      E := DrawString(pGraphics, Text, hFont, hFormat, pBrush, RC)

   if !PassBrush
      DeleteBrush(pBrush)
   DeleteStringFormat(hFormat)   
   DeleteFont(hFont)
   DeleteFontFamily(hFamily)
   return E ? E : ReturnRC
}

DeleteBrush(pBrush)
{
   return DllCall("gdiplus\GdipDeleteBrush", Ptr, pBrush)
}

CloneBrush(pBrush)
{
   DllCall("gdiplus\GdipCloneBrush", Ptr, pBrush, PtrP, pBrushClone)
   return pBrushClone
}

FontFamilyCreate(Font)
{
   DllCall("gdiplus\GdipCreateFontFamilyFromName", WStr, Font, Ptr, 0, PtrP, hFamily)
   return hFamily
}

FontCreate(hFamily, Size, Style=0)
{
   DllCall("gdiplus\GdipCreateFont", Ptr, hFamily, Float, Size, Int, Style, Int, 0, PtrP, hFont)
   return hFont
}

DeleteGraphics(pGraphics)
{
   return DllCall("gdiplus\GdipDeleteGraphics", Ptr, pGraphics)
}

StringFormatCreate(Format=0, Lang=0)
{
   DllCall("gdiplus\GdipCreateStringFormat", Int, Format, Int, Lang, PtrP, hFormat)
   return hFormat
}

BrushCreateSolid(ARGB=0xff000000)
{
   DllCall("gdiplus\GdipCreateSolidFill", UInt, ARGB, PtrP, pBrush)
   return pBrush
}

CreateRectF(ByRef RectF, x, y, w, h)
{
   VarSetCapacity(RectF, 16)
   NumPut(x, RectF, 0, "float"), NumPut(y, RectF, 4, "float"), NumPut(w, RectF, 8, "float"), NumPut(h, RectF, 12, "float")
}

SetStringFormatAlign(hFormat, Align)
{
   return DllCall("gdiplus\GdipSetStringFormatAlign", Ptr, hFormat, Int, Align)
}

SetTextRenderingHint(pGraphics, RenderingHint)
{
   return DllCall("gdiplus\GdipSetTextRenderingHint", Ptr, pGraphics, Int, RenderingHint)
}

MeasureString(pGraphics, sString, hFont, hFormat, ByRef RectF)
{
   VarSetCapacity(RC, 16)
   DllCall("gdiplus\GdipMeasureString", Ptr, pGraphics
      , WStr, sString, Int, -1, Ptr, hFont, Ptr, &RectF, Ptr, hFormat, Ptr, &RC, UIntP, Chars, UIntP, Lines)
   return &RC ? NumGet(RC, 0, "float") "|" NumGet(RC, 4, "float") "|" NumGet(RC, 8, "float") "|" NumGet(RC, 12, "float") "|" Chars "|" Lines : 0
}

DrawString(pGraphics, sString, hFont, hFormat, pBrush, ByRef RectF)
{
   return DllCall("gdiplus\GdipDrawString", Ptr, pGraphics
      , WStr, sString, Int, -1, Ptr, hFont, Ptr, &RectF, Ptr, hFormat, Ptr, pBrush)
}

DeleteStringFormat(hFormat)
{
   return DllCall("gdiplus\GdipDeleteStringFormat", Ptr, hFormat)
}

DeleteFont(hFont)
{
   return DllCall("gdiplus\GdipDeleteFont", Ptr, hFont)
}

DeleteFontFamily(hFamily)
{
   return DllCall("gdiplus\GdipDeleteFontFamily", Ptr, hFamily)
}

DeleteDC(hdc)
{
   return DllCall("DeleteDC", Ptr, hdc)
}

GetDC(hwnd=0)
{
   return DllCall("GetDC", Ptr, hwnd, Ptr)
}

ReleaseDC(hdc, hwnd=0)
{
   return DllCall("ReleaseDC", Ptr, hwnd, Ptr, hdc)
}

UpdateLayeredWindow(hwnd, hdc, x="", y="", w="", h="", Alpha=255)
{
   if ((x != "") && (y != ""))
      VarSetCapacity(pt, 8), NumPut(x, pt, 0, "UInt"), NumPut(y, pt, 4, "UInt")

   if (w = "") ||(h = "")
      WinGetPos,,, w, h, ahk_id %hwnd%
   
   return DllCall("UpdateLayeredWindow", Ptr, hwnd, Ptr, 0, Ptr, ((x = "") && (y = "")) ? 0 : &pt
   , Int64P, w|h<<32, Ptr, hdc, Int64P, 0, UInt, 0, UIntP, Alpha<<16|1<<24, UInt, 2)
}
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.30.01 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

25

Re: AHK: Бегущая строка


#SingleInstance Force
#Persistent  
#NoEnv
SetBatchLines -1
ListLines Off


global hGuiBack, hGuiString, hdc, XDiff, YDiff, XGuiString, YGuiString

Text = Следующая станция "Международная".
SleepDuration = 1  ; при уменьшении скорость возрастёт
Font = Arial
Size := 700
Margin := 0   ; отступ от верхнего края строки

W := 1600
H := 900

DllCall("Winmm\timeBeginPeriod", UInt, 3)
OnExit, Exit

Gui, Back:+hwndhGuiBack
Gui, Back:Color, Gray
Gui, Back:Margin, 0, 0
Gui, Back:Add, Pic, w%W% h%H%, Pic1.jpg
Gui, Back:Show, w%W% h%H%

Gui, -Caption +E0x80020 +OwnerBack +ToolWindow +hwndhGuiString
Gui, Show, NA

OnMessage(0x46, "WM_WINDOWPOSCHANGING")

pToken := Startup()

hbm := CreateDIBSection(W, H)
hdc := DllCall("CreateCompatibleDC", Ptr, 0, Ptr)
obm := DllCall("SelectObject", Ptr, hdc, Ptr, hbm, Ptr)
DllCall("gdiplus\GdipCreateFromHDC", Ptr, hdc, PtrP, G)
DllCall("gdiplus\GdipSetSmoothingMode", Ptr, G, Int, 4)

VarSetCapacity(WI, 60), NumPut(60, WI, "UInt")
DllCall("GetWindowInfo", Ptr, hGuiBack, Ptr, &WI)
XGui := NumGet(WI, 4, "UInt"), YGui := NumGet(WI, 8, "UInt")
XClient := NumGet(WI, 20, "UInt"), YClient := NumGet(WI, 24, "UInt")
XDiff := XClient - XGui, YDiff := YClient - YGui

XGuiString := XClient 
YGuiString := YClient 

Loop
{
   DllCall("gdiplus\GdipGraphicsClear", Ptr, G, UInt, 0)

   Options := "x" W - mod(A_Index, wt ? wt : 100000)*2 " y" Margin " cFFFFAA00 r4 s" Size
   RC := TextToGraphics(G, Text, Options, Font, wt ? wt : 100000, H)
   wt := RegExReplace(RC, "(.*?\|){2}(.*?)(\.\d+)?\|.*", "$2") + W

   UpdateLayeredWindow(hGuiString, hdc, XGuiString, YGuiString, W, H)
   
   DllCall("Sleep", UInt, SleepDuration)
}
return

~Esc::
GuiEscape: 
   ExitApp 
   
BackGuiClose:
   ExitApp

Exit:
   DllCall("Winmm\timeEndPeriod", UInt, 3)
   DllCall("SelectObject", Ptr, hdc, Ptr, obm, Ptr), DllCall("DeleteObject", Ptr, hbm)
   DeleteDC(hdc), DllCall("gdiplus\GdipDeleteGraphics", Ptr, G), Shutdown(pToken)
   ExitApp
   
WM_WINDOWPOSCHANGING(wp, lp, msg, hwnd)
{
   x := NumGet(lp+0, A_PtrSize*2, "UInt"), y := NumGet(lp+0, A_PtrSize*2+4, "UInt")
   if (x = 0 && y = 0)
      return
   UpdateLayeredWindow(hGuiString, hdc, XGuiString := x + XDiff + 20, YGuiString := y + YDiff + 20, 350, 50)
}
   
Startup()
{
   if !DllCall("GetModuleHandle", Str, "gdiplus", Ptr)
      DllCall("LoadLibrary", Str, "gdiplus")
   VarSetCapacity(si, A_PtrSize = 8 ? 24 : 16, 0), si := Chr(1)
   DllCall("gdiplus\GdiplusStartup", UPtrP, pToken, Ptr, &si, Ptr, 0)
   return pToken
}

Shutdown(pToken)
{
   DllCall("gdiplus\GdiplusShutdown", UPtr, pToken)
   if hModule := DllCall("GetModuleHandle", Str, "gdiplus", Ptr)
      DllCall("FreeLibrary", Ptr, hModule)
   return 0
}

CreateDIBSection(w, h, hdc="", bpp=32, ByRef ppvBits=0)
{
   hdc2 := hdc ? hdc : GetDC()
   VarSetCapacity(bi, 40, 0)
   NumPut(w, bi, 4, "UInt"), NumPut(h, bi, 8, "UInt"), NumPut(40, bi, 0, "UInt"), NumPut(1, bi, 12, "ushort"), NumPut(0, bi, 16), NumPut(bpp, bi, 14, "ushort")
   hbm := DllCall("CreateDIBSection", Ptr , hdc2, Ptr , &bi, UInt , 0, PtrP, ppvBits, Ptr , 0, UInt , 0, Ptr)

   if !hdc
      ReleaseDC(hdc2)
   return hbm
}

TextToGraphics(pGraphics, Text, Options, Font="Arial", Width="", Height="", Measure=0)
{
   IWidth := Width, IHeight:= Height
   
   RegExMatch(Options, "i)X([\-\d\.]+)(p*)", xpos)
   RegExMatch(Options, "i)Y([\-\d\.]+)(p*)", ypos)
   RegExMatch(Options, "i)W([\-\d\.]+)(p*)", Width)
   RegExMatch(Options, "i)H([\-\d\.]+)(p*)", Height)
   RegExMatch(Options, "i)C(?!(entre|enter))([a-f\d]+)", Colour)
   RegExMatch(Options, "i)Top|Up|Bottom|Down|vCentre|vCenter", vPos)
   RegExMatch(Options, "i)NoWrap", NoWrap)
   RegExMatch(Options, "i)R(\d)", Rendering)
   RegExMatch(Options, "i)S(\d+)(p*)", Size)

   if !DeleteBrush(CloneBrush(Colour2))
      PassBrush := 1, pBrush := Colour2
   
   if !(IWidth && IHeight) && (xpos2 || ypos2 || Width2 || Height2 || Size2)
      return -1

   Style := 0, Styles := "Regular|Bold|Italic|BoldItalic|Underline|Strikeout"
   Loop, Parse, Styles, |
   {
      if RegExMatch(Options, "\b" A_loopField)
      Style |= (A_LoopField != "StrikeOut") ? (A_Index-1) : 8
   }
  
   Align := 0, Alignments := "Near|Left|Centre|Center|Far|Right"
   Loop, Parse, Alignments, |
   {
      if RegExMatch(Options, "\b" A_loopField)
         Align |= A_Index//2.1      ; 0|0|1|1|2|2
   }

   xpos := (xpos1 != "") ? xpos2 ? IWidth*(xpos1/100) : xpos1 : 0
   ypos := (ypos1 != "") ? ypos2 ? IHeight*(ypos1/100) : ypos1 : 0
   Width := Width1 ? Width2 ? IWidth*(Width1/100) : Width1 : IWidth
   Height := Height1 ? Height2 ? IHeight*(Height1/100) : Height1 : IHeight
   if !PassBrush
      Colour := "0x" (Colour2 ? Colour2 : "ff000000")
   Rendering := ((Rendering1 >= 0) && (Rendering1 <= 5)) ? Rendering1 : 4
   Size := (Size1 > 0) ? Size2 ? IHeight*(Size1/100) : Size1 : 12

   hFamily := FontFamilyCreate(Font)
   hFont := FontCreate(hFamily, Size, Style)
   FormatStyle := NoWrap ? 0x4000 | 0x1000 : 0x4000
   hFormat := StringFormatCreate(FormatStyle)
   pBrush := PassBrush ? pBrush : BrushCreateSolid(Colour)
   if !(hFamily && hFont && hFormat && pBrush && pGraphics)
      return !pGraphics ? -2 : !hFamily ? -3 : !hFont ? -4 : !hFormat ? -5 : !pBrush ? -6 : 0
   
   CreateRectF(RC, xpos, ypos, Width, Height)
   SetStringFormatAlign(hFormat, Align)
   SetTextRenderingHint(pGraphics, Rendering)
   ReturnRC := MeasureString(pGraphics, Text, hFont, hFormat, RC)

   if vPos
   {
      StringSplit, ReturnRC, ReturnRC, |
      
      if (vPos = "vCentre") || (vPos = "vCenter")
         ypos += (Height-ReturnRC4)//2
      else if (vPos = "Top") || (vPos = "Up")
         ypos := 0
      else if (vPos = "Bottom") || (vPos = "Down")
         ypos := Height-ReturnRC4
      
      CreateRectF(RC, xpos, ypos, Width, ReturnRC4)
      ReturnRC := MeasureString(pGraphics, Text, hFont, hFormat, RC)
   }

   if !Measure
      E := DrawString(pGraphics, Text, hFont, hFormat, pBrush, RC)

   if !PassBrush
      DeleteBrush(pBrush)
   DeleteStringFormat(hFormat)   
   DeleteFont(hFont)
   DeleteFontFamily(hFamily)
   return E ? E : ReturnRC
}

DeleteBrush(pBrush)
{
   return DllCall("gdiplus\GdipDeleteBrush", Ptr, pBrush)
}

CloneBrush(pBrush)
{
   DllCall("gdiplus\GdipCloneBrush", Ptr, pBrush, PtrP, pBrushClone)
   return pBrushClone
}

FontFamilyCreate(Font)
{
   DllCall("gdiplus\GdipCreateFontFamilyFromName", WStr, Font, Ptr, 0, PtrP, hFamily)
   return hFamily
}

FontCreate(hFamily, Size, Style=0)
{
   DllCall("gdiplus\GdipCreateFont", Ptr, hFamily, Float, Size, Int, Style, Int, 0, PtrP, hFont)
   return hFont
}

DeleteGraphics(pGraphics)
{
   return DllCall("gdiplus\GdipDeleteGraphics", Ptr, pGraphics)
}

StringFormatCreate(Format=0, Lang=0)
{
   DllCall("gdiplus\GdipCreateStringFormat", Int, Format, Int, Lang, PtrP, hFormat)
   return hFormat
}

BrushCreateSolid(ARGB=0xff000000)
{
   DllCall("gdiplus\GdipCreateSolidFill", UInt, ARGB, PtrP, pBrush)
   return pBrush
}

CreateRectF(ByRef RectF, x, y, w, h)
{
   VarSetCapacity(RectF, 16)
   NumPut(x, RectF, 0, "float"), NumPut(y, RectF, 4, "float"), NumPut(w, RectF, 8, "float"), NumPut(h, RectF, 12, "float")
}

SetStringFormatAlign(hFormat, Align)
{
   return DllCall("gdiplus\GdipSetStringFormatAlign", Ptr, hFormat, Int, Align)
}

SetTextRenderingHint(pGraphics, RenderingHint)
{
   return DllCall("gdiplus\GdipSetTextRenderingHint", Ptr, pGraphics, Int, RenderingHint)
}

MeasureString(pGraphics, sString, hFont, hFormat, ByRef RectF)
{
   VarSetCapacity(RC, 16)
   DllCall("gdiplus\GdipMeasureString", Ptr, pGraphics
      , WStr, sString, Int, -1, Ptr, hFont, Ptr, &RectF, Ptr, hFormat, Ptr, &RC, UIntP, Chars, UIntP, Lines)
   return &RC ? NumGet(RC, 0, "float") "|" NumGet(RC, 4, "float") "|" NumGet(RC, 8, "float") "|" NumGet(RC, 12, "float") "|" Chars "|" Lines : 0
}

DrawString(pGraphics, sString, hFont, hFormat, pBrush, ByRef RectF)
{
   return DllCall("gdiplus\GdipDrawString", Ptr, pGraphics
      , WStr, sString, Int, -1, Ptr, hFont, Ptr, &RectF, Ptr, hFormat, Ptr, pBrush)
}

DeleteStringFormat(hFormat)
{
   return DllCall("gdiplus\GdipDeleteStringFormat", Ptr, hFormat)
}

DeleteFont(hFont)
{
   return DllCall("gdiplus\GdipDeleteFont", Ptr, hFont)
}

DeleteFontFamily(hFamily)
{
   return DllCall("gdiplus\GdipDeleteFontFamily", Ptr, hFamily)
}

DeleteDC(hdc)
{
   return DllCall("DeleteDC", Ptr, hdc)
}

GetDC(hwnd=0)
{
   return DllCall("GetDC", Ptr, hwnd, Ptr)
}

ReleaseDC(hdc, hwnd=0)
{
   return DllCall("ReleaseDC", Ptr, hwnd, Ptr, hdc)
}

UpdateLayeredWindow(hwnd, hdc, x="", y="", w="", h="", Alpha=255)
{
   if ((x != "") && (y != ""))
      VarSetCapacity(pt, 8), NumPut(x, pt, 0, "UInt"), NumPut(y, pt, 4, "UInt")

   if (w = "") ||(h = "")
      WinGetPos,,, w, h, ahk_id %hwnd%
   
   return DllCall("UpdateLayeredWindow", Ptr, hwnd, Ptr, 0, Ptr, ((x = "") && (y = "")) ? 0 : &pt
   , Int64P, w|h<<32, Ptr, hdc, Int64P, 0, UInt, 0, UIntP, Alpha<<16|1<<24, UInt, 2)
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg