Lies in der Funktionsbeschreibung nach, welche Werte das Array enthalten muß. Und genau so baust du es dann auf.
Übrigens: StringSplit kann man auch mit einem zusätzlichen Flag aufrufen, dann wird kein Zähler an [0] zurück gegeben.
Lies in der Funktionsbeschreibung nach, welche Werte das Array enthalten muß. Und genau so baust du es dann auf.
Übrigens: StringSplit kann man auch mit einem zusätzlichen Flag aufrufen, dann wird kein Zähler an [0] zurück gegeben.
Local $aTimeFillerArray = [ 0 , 0, 0]
Das ist KEINE gültige Arraydeklaration!
Schau noch mal genau hin. Wenn du den Fehler selber siehst, kannst du es dir besser merken.
OK, schau bitte in meine Signatur, dort findest du ein Array Tutorial. Bitte gründlich lesen (Deklaration und Wertzuweisung)!
Dann wirst du merken, was du falsch gemacht hast.
Kannst du so machen:
Global $iWait = 60 ; Sekunden
Global $hGui = GUICreate('Test')
Global $bt1 = GUICtrlCreateButton('Starte Func _1', 10, 20, 150, 25)
GUISetState()
; Starte Zeitnahme
Global $Timer = TimerInit()
Global $bStarted = False
While True
If (Not $bStarted) And TimerDiff($Timer) >= $iWait*1000 Then
$bStarted = True
_1() ; starte Funktion
EndIf
Switch GUIGetMsg()
Case -3
Exit
Case $bt1
If (Not $bStarted) Then
$bStarted = True
_1() ; starte Funktion
EndIf
EndSwitch
WEnd
Func _1()
ConsoleWrite('"Func _1" wurde gestartet' & @CRLF)
EndFunc
Alles anzeigen
Zeig uns bitte mal etwas mehr Code, auch mit der Deklaration und Befüllung des Arrays.
Zum Anzeigen von Code im Post verwende bitte aus dem Menü im Editfeld: </> (Code)
Vorab:
Das ist hier keine superelegante Lösung mit Zugriff auf DOM, sondern eher ein Workaround um auch ohne IE-Objekt Html in eigene GUI einbetten zu können.
Ich weiß auch nicht, ob sich Opera überhaupt anzapfen lässt, um direkt mit dem Objekt zu interagieren. Ich gehe hier einfach den Weg: Html-Datei im Temp-Ordner erstellen und als Parameter an den Opera-Aufruf anhängen. Das Opera-Fenster greife ich mir dann und hänge es als Child in eine eigene GUI.
Einen Handling-Nachteil haben wir allerdings: Ich kann zwar in meiner angezeigten Html-Datei Referenzen auf Online-Seiten einfügen und dann in der Anwendung diese auch anzeigen - ABER: Ich komme nicht mehr zurück, da ich keine Navigationsmöglichkeit habe, ich kann immer nur eine neue Html-Datei erstellen und das Fenster Refreshen, um diese zu laden. Referenzen auf Textmarken funktionieren aber tadellos. Diese UDF ist gedacht um lokale Html-Dateien/Inhalte in eine GUI einzubetten.
Opera habe ich verwendet, weil dieser Browser nach allem, was ich bisher gesehen habe, der einzige ist, der sich soweit personalisieren lässt (optisch), dass nur das nackte Fenster ohne Menüs, Bars, Statuszeile übrig bleibt. Die verwendete portable Version 12.18 ist mit ca. 30 MB auch eine der kleinsten von allen portablen Browsern. (Portabel deshalb, damit man diesen auch bei Projekten mitgeben kann). Wenn ihr den Browser selber laden möchtet: Opera@USB für Windows v12.18. Anschließend müssen über das Konfigurationsmenü (Rechtsklick in den geöffneten Browser) alle Anzeigen für Menüs, Bars, Statuszeile deaktiviert werden.
Ich biete hier einen Gesamt-DL aller Dateien (UDF + Bsp.) mit Browser und bereits vorkonfiguriertem Profil zum DL (s. DL_embedded.zip.txt im Anhang).
Bei einzelnem Download:
In einem Ordner legt bitte folgende Struktur an
<fonts> enthält "SourceCodePro" für "array_tut.htm"
<Opera> portable Version 12.18
array_tut.htm Testdatei, verwendet in "..ExampleHelp.au3"
OperaEmbedded.au3 UDF
OperaEmbedded_ExampleHelp.au3 Beispiel
OperaEmbedded_ExampleTable.au3 Beispiel
;-- TIME_STAMP 2020-11-19 16:13:36 v 0.1
#include-once
#include <WinAPISysWin.au3>
#include <WindowsConstants.au3>
; Opera@USB für Windows v12.18
; DL: https://www.netzwelt.de/software-download/26792-opera-usb.html
; only 1 embedded window is possible
; ".\Opera\profile\operaprefs.ini" - if something fails with the view: delete the profile folder, a new one will created
; and disable all bars and menus in config menu (right click in opened opera window)
Opt('MustDeclareVars', 1)
OnAutoItExitRegister('_OperaEmbedded_Exit')
Global Const $gc_PathBrowser = @ScriptDir & '\Opera\Opera.exe'
Global $g_PathTempHtml = @TempDir & '\OperaEmbeddedTemp.html'
Global $g_hOperaEmbedded, $g_hMain, $g_PID = Null
Func _OperaEmbedded_Exit()
If $g_PID = Null Then Exit
FileDelete($g_PathTempHtml)
WinClose($g_hOperaEmbedded)
ProcessClose($g_PID)
EndFunc
; negative values (width/height) treated as: difference of client.width/height minus value
Func _OperaEmbedded_Create($_hParent, $_x, $_y, $_w=Default, $_h=Default, $_bBorder=False)
Local Static $bActive = False
If $bActive Then
Return SetError(1,0,0) ; only one instance possible
Else
$bActive = True
EndIf
$g_hMain = $_hParent
$g_PID = @AutoItPID
_OperaEmbedded_CreateHtml('', '', False) ; empty file for start
__OperaEmbedded_StartHidden()
Local $iStyle = $_bBorder ? (BitOr($WS_CHILD,$WS_BORDER)) : $WS_CHILD
_WinAPI_SetParent($g_hOperaEmbedded, $g_hMain)
; set style fails sometimes (don't know why) - do it in a loop until successfully
Do
Sleep(10)
Until _WinAPI_SetWindowLong($g_hOperaEmbedded, $GWL_STYLE, $iStyle) <> 0
_WinAPI_SetWindowLong($g_hOperaEmbedded, $GWL_EXSTYLE, $WS_EX_MDICHILD)
Local $clientWidth = _WinAPI_GetClientWidth($g_hMain)
Local $clientHeight = _WinAPI_GetClientHeight($g_hMain)
If $_w < 0 Then
$_w = $clientWidth - Abs($_w)
ElseIf $_w > $clientWidth Or $_w = Default Then
$_w = $clientWidth
EndIf
If $_h < 0 Then
$_h = $clientHeight - Abs($_h)
ElseIf $_h > $clientHeight Or $_h = Default Then
$_h = $clientHeight
EndIf
WinMove($g_hOperaEmbedded, '', $_x, $_y, $_w, $_h)
EndFunc
Func _OperaEmbedded_CreateHtml($_Body='', $_Style=-1, $_JS=-1, $_bRefresh=True)
Local Static $sStyle = '', $sJS = ''
If $_Style <> -1 Then $sStyle = $_Style
If $_JS <> -1 Then $sJS = $_JS
Local $sHtml = '<!DOCTYPE html><html>' & _
'<head><meta charset="utf-8">' & _
'<title>OperaEmbeddedWindow</title>' & _ ; title is invisible but fix for window detection
'<script language="JavaScript">' & $sJS & '</script>' & _
'<style type="text/css">' & $sStyle & '</style>' & _
'</head>' & $_Body & '</html>' & @CRLF
Local $fH = FileOpen($g_PathTempHtml, 8+2)
FileWrite($fH, $sHtml)
FileClose($fH)
If $_bRefresh Then _OperaEmbedded_RefreshView()
EndFunc
Func _OperaEmbedded_HtmlFromFile($_sFileHtml, $_aReplaces=Null)
Local $sHtml = FileRead($_sFileHtml)
$sHtml = StringRegExpReplace($sHtml, '<title>[^<]+<', '<title>OperaEmbeddedWindow<', 1)
If IsArray($_aReplaces) Then
For $i = 0 To UBound($_aReplaces) -1
$sHtml = StringReplace($sHtml, $_aReplaces[$i][0], $_aReplaces[$i][1])
Next
EndIf
Local $fH = FileOpen($g_PathTempHtml, 8+2+512) ; ANSI mode
FileWrite($fH, $sHtml)
FileClose($fH)
EndFunc
Func _OperaEmbedded_Show($_iState=@SW_SHOWNA)
_WinAPI_ShowWindow($g_hOperaEmbedded, $_iState)
EndFunc
Func _OperaEmbedded_RefreshView()
WinActivate($g_hOperaEmbedded)
WinWaitActive($g_hOperaEmbedded, 5)
Send("{F5}")
WinSetState($g_hOperaEmbedded, '', @SW_SHOWNA)
WinActivate($g_hMain)
EndFunc
Func __OperaEmbedded_StartHidden()
ShellExecute($gc_PathBrowser, $g_PathTempHtml, @TempDir, '', @SW_HIDE)
Local $optOld = Opt('WinTitleMatchMode', 2)
$g_hOperaEmbedded = WinWait('OperaEmbeddedWindow')
Opt('WinTitleMatchMode', $optOld)
EndFunc
Alles anzeigen
Eine Html-Datei kann man natürlich mit: ShellExecute(PathBrowser, @ScriptDir & "\meineDatei.html") ausführen. Jedoch dann mit Titel und Icon des Browserfensters.
Ich verwende hier zum Aktualisieren der Inhalte, mangels anderer Techniken, das Senden von F5. Falls jemand einen eleganteren Weg kennt, immer her damit.
ich möchte mehrere Daten speichern
Daten = Datumswerte ![]()
in einer externen Applikation
Da du erkennen konntest, dass es sich um ein SysDateTimePick32 - Control handelt (AutoItWindowInfo ?), brauchst du das Handle/die ID dieses Controls. und kannst dann mit den Funktionen aus der AutoIt-UDF darauf zugreifen.
Schau dir mal das Bsp. zu _GUICtrlDTP_SetSystemTime an.
Ich weiß jetzt nicht welcher Kalender dort verwendet wird, evtl. hilft dir dann auch das hier: Maske zum Markieren in Monatskalender erstellen
Findet man diese Alt- und Ctrl-Funktionen auch in der SciTE Doku?
ich war bisher erfolglos
(Man findet sie auch hier im Forum in alten Posts, hier Blockauswahl)
Du hast schon richtig verlinkt. Es steht halt nicht als Liste, sondern mitten im Text:
Bereichsmarkierung:
Kapitel: Standard Editing
Text editing in SciTE works similarly to most Macintosh or Windows editors with the added feature of automatic syntax styling. SciTE can hold multiple files in memory at one time but only one file will be visible. Rectangular blocks of text can be selected in SciTE by holding down the Alt key on Windows or the Ctrl key on GTK+ while dragging the mouse over the text.
....
....
Mehrere Cursorpositionen:
Kapitel: Defined variables in properties files
selection.multiple | Set selection.multiple to make multiple selections with the mouse by holding down the Ctrl key.
Daraus resultierend hatte @progandy den Blockeditor aus NPP nachgeskripted.
Wenn du die STRG - Taste gedrückt hältst kannst du durch Mausklick mehrere Cursorpositionen aktivieren. Unbeabsichtigt kann das nicht passieren - hast du eine Katze deren Pfote ständig auf STRG drückt? ![]()
Erstmal danke für deine Antwort das soll in zwei Felder Zufällig von der txt Datei Texte eintragen klappt alles gut aber ich schaff es irgendwie nicht mit einer zweiten fileName ??
OK, du bist neu. - Ein paar Hinweise:
Wenn du Hilfe benötigst, solltest du dein Problem so genau, wie möglich beschreiben.
Z.B.
Ich habe eine Textdatei mit folgendem Aufbau (noch besser Beispieldatei anhängen, evtl. sensible Daten unkenntlich machen) .....
Ich möchte an der Position X (gekennzeichnet durch ...) und an der Position Y (gekennzeichnet durch ...) folgende Daten eintragen.
Probiert habe ich folgendes ...
Deine jetzige Beschreibung wirft mehr Fragen auf, als dass sie Antworten gibt.
Schiebst du dann bitte noch eine korrigierte, bzw. finale Version hoch - danke!
Hier zwei Varianten:
;-- TIME_STAMP 2020-11-12 18:15:27
; Variante für einzelnes Fenster
Opt('MustDeclareVars', 1)
#include <WinAPISysWin.au3>
#include <WindowsConstants.au3>
Global $g_aMinMax[4] ; [widthMin,heightMin,widthMax,heightMax]
Global $hGui = GUICreate('Sizing', 400, 300, -1, -1, BitOR($WS_SYSMENU, $WS_MINIMIZEBOX, $WS_MAXIMIZEBOX, $WS_SIZEBOX))
; Höhe und Breite in den Grenzen änderbar
_GuiMinMax(200, 150, 800, 500)
; nur Höhe änderbar (min: 150, max: ohne Limit)
; !!! Wird Breite oder Höhe in Min auf "-1" gesetzt MUSS der korrespondierende Wert in Max auch "-1" sein. Sonst Änderung nur einmalig.
;~ _GuiMinMax(-1, 150, -1, 0) ; "0": keine Limitierung, "-1": keine Größenänderung möglich!
; nur Breite änderbar (min: 150, max: 900)
;~ _GuiMinMax(200, -1, 900, -1)
GuiRegisterMsg($WM_WINDOWPOSCHANGING, '_SizeWindowProc')
GUISetState()
While True
Switch GUIGetMsg()
Case -3
Exit
EndSwitch
WEnd
Func _GuiMinMax($_wMin=-1, $_hMin=-1, $_wMax=-1, $_hMax=-1)
If $_wMin > -1 Then $g_aMinMax[0] = $_wMin
If $_hMin > -1 Then $g_aMinMax[1] = $_hMin
If $_wMax > -1 Then $g_aMinMax[2] = $_wMax
If $_hMax > -1 Then $g_aMinMax[3] = $_hMax
EndFunc
Func _SizeWindowProc($_hWnd, $_iMsg, $_iwParam, $_ilParam)
Local $tRectWnd = _WinAPI_GetWindowRect($_hWnd)
Local $iW_Wnd = $tRectWnd.Right - $tRectWnd.Left
Local $iH_Wnd = $tRectWnd.Bottom - $tRectWnd.Top
Local $iX_Wnd = $tRectWnd.Left
Local $iY_Wnd = $tRectWnd.Top
Local $wMin = $g_aMinMax[0]
Local $hMin = $g_aMinMax[1]
Local $wMax = $g_aMinMax[2]
Local $hMax = $g_aMinMax[3]
Local $tWINDOWPOS = DllStructCreate("struct; HWND hwndInsertAfter;HWND hwnd;INT x;INT y;INT cx;INT cy;UINT flags; endstruct", $_ilParam)
; undocumented flags: 0x8000, 0x1000 and 0x0800
Local Const $SWP_FROZENWINDOW = 0x8000
If $tWINDOWPOS.cx < $wMin Then ; target width too small
$tWINDOWPOS.cx = $wMin ; set to min
$tWINDOWPOS.x = $iX_Wnd ; keep the current x value
EndIf
If $tWINDOWPOS.cy < $hMin Then ; target height too small
$tWINDOWPOS.cy = $hMin ; set to min
$tWINDOWPOS.y = $iY_Wnd ; keep the current y value
EndIf
If $tWINDOWPOS.cx > $wMax Then ; target width too large
$tWINDOWPOS.cx = $wMax ; set to max
$tWINDOWPOS.x = $iX_Wnd ; keep the current x value
EndIf
If $tWINDOWPOS.cy > $hMax Then ; target height too large
$tWINDOWPOS.cy = $hMax ; set to max
$tWINDOWPOS.y = $iY_Wnd ; keep the current y value
EndIf
If (BitAND($tWINDOWPOS.flags, $SWP_FROZENWINDOW)) Then _WinAPI_ShowWindow($_hWnd, @SW_RESTORE)
Return 0 ; avoid default window processing
EndFunc
Alles anzeigen
;-- TIME_STAMP 2020-11-12 18:03:23
; Variante für mehrere Fenster
#include <WinAPISysWin.au3>
#include <WindowsConstants.au3>
Opt('MustDeclareVars', 1)
OnAutoItExitRegister("_HookCleanUp")
Global $g_hSizeHook, $g_hSizeProc = Null
Global $g_aWnd[100][5] = [[0]] ; [[counter],[hWnd,widthMin,heightMin,widthMax,heightMax], ..]
; --------------------------------------------------------------------------------------------------
Global $hGui = GUICreate('Sizing', 400, 300, -1, -1, BitOR($WS_SYSMENU, $WS_MINIMIZEBOX, $WS_MAXIMIZEBOX, $WS_SIZEBOX))
; Höhe und Breite in den Grenzen änderbar
_GuiMinMax($hGui, 200, 150, 800, 500)
; nur Höhe änderbar (min: 150, max: ohne Limit)
; !!! Wird Breite oder Höhe in Min auf "-1" gesetzt MUSS der korrespondierende Wert in Max auch "-1" sein. Sonst Änderung nur einmalig.
;~ _GuiMinMax($hGui, -1, 150, -1, 0) ; "0": keine Limitierung, "-1": keine Größenänderung möglich!
; nur Breite änderbar (min: 150, max: 900)
;~ _GuiMinMax($hGui, 200, -1, 900, -1)
GUISetState()
While True
Switch GUIGetMsg()
Case -3
Exit
EndSwitch
WEnd
; --------------------------------------------------------------------------------------------------
Func _GuiMinMax($_hWnd, $_wMin=-1, $_hMin=-1, $_wMax=-1, $_hMax=-1)
_SizeHook($_hWnd)
Local $index = -1
For $i = 1 To $g_aWnd[0][0]
If $g_aWnd[$i][0] = $_hWnd Then
$index = $i
ExitLoop
EndIf
Next
If $index = -1 Then Return
If $_wMin > -1 Then $g_aWnd[$index][1] = $_wMin
If $_hMin > -1 Then $g_aWnd[$index][2] = $_hMin
If $_wMax > -1 Then $g_aWnd[$index][3] = $_wMax
If $_hMax > -1 Then $g_aWnd[$index][4] = $_hMax
EndFunc
Func _SizeHook($_hWnd)
If $g_aWnd[0][0] = UBound($g_aWnd) -1 Then ReDim $g_aWnd[UBound($g_aWnd) +100][5]
For $i = 1 To $g_aWnd[0][0]
If $g_aWnd[$i][0] = $_hwnd Then Return
Next
$g_aWnd[0][0] += 1
$g_aWnd[$g_aWnd[0][0]][0] = $_hWnd
$g_aWnd[$g_aWnd[0][0]][1] = -1
$g_aWnd[$g_aWnd[0][0]][2] = -1
$g_aWnd[$g_aWnd[0][0]][3] = -1
$g_aWnd[$g_aWnd[0][0]][4] = -1
If $g_hSizeProc = Null Then $g_hSizeProc = DllCallbackRegister('_SizeWindowProc', 'ptr', 'hwnd;uint;wparam;lparam')
$g_hSizeHook = _WinAPI_SetWindowLong($_hWnd, $GWL_WNDPROC, DllCallbackGetPtr($g_hSizeProc))
EndFunc
Func _HookCleanUp()
If $g_hSizeProc = Null Then Return
For $i = 1 To $g_aWnd[0][0] ; reset to default window procedure
If WinExists($g_aWnd[$i][0]) Then _WinAPI_SetWindowLong($g_aWnd[$i][0], $GWL_WNDPROC, $g_hSizeHook)
Next
DllCallbackFree($g_hSizeProc)
EndFunc
Func _SizeWindowProc($_hWnd, $_iMsg, $_iwParam, $_ilParam)
If $_iMsg <> $WM_WINDOWPOSCHANGING Then _ ; Sent to a window whose size, position, or place in the Z order is about to change
Return _WinAPI_CallWindowProc($g_hSizeHook, $_hWnd, $_iMsg, $_iwParam, $_ilParam)
Local $index = -1
For $i = 1 To $g_aWnd[0][0]
If $g_aWnd[$i][0] = $_hWnd Then
$index = $i
ExitLoop
EndIf
Next
If $index = -1 Then Return _WinAPI_CallWindowProc($g_hSizeHook, $_hWnd, $_iMsg, $_iwParam, $_ilParam) ; default window processing
Local $tRectWnd = _WinAPI_GetWindowRect($_hWnd)
Local $iW_Wnd = $tRectWnd.Right - $tRectWnd.Left
Local $iH_Wnd = $tRectWnd.Bottom - $tRectWnd.Top
Local $iX_Wnd = $tRectWnd.Left
Local $iY_Wnd = $tRectWnd.Top
Local $wMin = $g_aWnd[$index][1]
Local $hMin = $g_aWnd[$index][2]
Local $wMax = $g_aWnd[$index][3]
Local $hMax = $g_aWnd[$index][4]
Local $tWINDOWPOS = DllStructCreate("struct; HWND hwndInsertAfter;HWND hwnd;INT x;INT y;INT cx;INT cy;UINT flags; endstruct", $_ilParam)
; undocumented flags: 0x8000, 0x1000 and 0x0800
Local Const $SWP_FROZENWINDOW = 0x8000
If $tWINDOWPOS.cx < $wMin Then ; target width too small
$tWINDOWPOS.cx = $wMin ; set to min
$tWINDOWPOS.x = $iX_Wnd ; keep the current x value
EndIf
If $tWINDOWPOS.cy < $hMin Then ; target height too small
$tWINDOWPOS.cy = $hMin ; set to min
$tWINDOWPOS.y = $iY_Wnd ; keep the current y value
EndIf
If $tWINDOWPOS.cx > $wMax Then ; target width too large
$tWINDOWPOS.cx = $wMax ; set to max
$tWINDOWPOS.x = $iX_Wnd ; keep the current x value
EndIf
If $tWINDOWPOS.cy > $hMax Then ; target height too large
$tWINDOWPOS.cy = $hMax ; set to max
$tWINDOWPOS.y = $iY_Wnd ; keep the current y value
EndIf
If (BitAND($tWINDOWPOS.flags, $SWP_FROZENWINDOW)) Then _WinAPI_ShowWindow($_hWnd, @SW_RESTORE)
Return 0 ; avoid default window processing
EndFunc
Alles anzeigen
Was willst du denn damit erreichen?
Send und MouseClick sind Befehle, die in einer Dateibearbeitung nichts zu suchen haben.
Dateieinhalte kann man im ganzen oder zeilenweise oder positionsorientiert lesen/schreiben.
Schau mal in der Hilfe folgende Begriffe und die Beispiele dazu an:
FileOpen, FileClose, FileRead, FileWrite, FileReadLine, FileWriteLine, FileGetPos, FileSetPos
ich habe festgestellt, dass bei Win+Up in der WINDOWPOS Struktur das Flag 0x00008000 gesetzt ist. Dies scheint ein undokumentiertes Flag zu sein.
Da habe ich mal in der Richtung gesucht, es gibt sogar 3 undokumentierte Flags: 0x8000, 0x1000 and 0x0800 - aber eine Erklärung dafür hat keiner so richtig.
Ich habe jetzt kurzerhand definiert:
Local Const $SWP_FROZENWINDOW = 0x8000
und angewendet dann:
If (BitAND($tWINDOWPOS.flags, $SWP_FROZENWINDOW)) Then _WinAPI_ShowWindow($_hWnd, @SW_RESTORE)
Danke für den Hinweis. Damit kann ich die anderen Messages außen vorlassen und brauch nur WM_WINDOWPOSCHANGING prüfen.
Oscars Hinweis auf die Forenregeln bezieht sich sicher auf das Fenster, welches du überwachst. "BlueStacks" ist ein Emulator und wird vorrangig für Spiele genutzt. Und deren Automatisierung verstößt gegen unsere Forenregeln.
Sei deshalb bei Anfragen so konkret wie möglich und benenne immer Roß und Reiter.
Ich benutze meist die WM_WINDOWPOSCHANGING
Ich habe das jetzt mal eingebunden. Damit werden tatsächlich alle Szenarien (auch Tastatur!) abgedeckt. ![]()
Alleine führt es aber nicht zum Ziel. Der Doppelklick auf die Titelleiste und Klick auf Maximize Button müssen separat abgefangen werden. WM_WINDOWPOSCHANGING verhindert sonst zwar die Größenänderung (Maxwerte werden gesetzt), danach ist das Fenster aber "eingefroren" und muss mit einem MOVE wieder freigegeben werden - dann springt aber die Größe auf den Zeitpunkt vor WM_WINDOWPOSCHANGING. Und dasselbe passiert bei Maximize per Tastatur (Win+Up).
Fehlt mir also noch eine saubere Lösung für Maximize per Tastatur.
Hier das Skript:
;-- TIME_STAMP 2020-11-09 12:21:38
#include <GUIConstantsEx.au3>
#include <WinAPISysWin.au3>
#include <WinAPIConv.au3>
#include <WindowsConstants.au3>
Opt('MustDeclareVars', 1)
OnAutoItExitRegister("_HookCleanUp")
Global Const $SC_MOVE = 0xF010
Global Const $SC_MINIMIZE = 0xF020
Global Const $SC_MAXIMIZE = 0xF030
Global $g_hSizeHook, $g_hSizeProc = Null
Global $g_aWnd[100][5] = [[0]] ; [[counter],[hWnd,widthMin,heightMin,widthMax,heightMax], ..]
; --------------------------------------------------------------------------------------------------
Global $hGui = GUICreate('Sizing', 400, 300, -1, -1, BitOR($WS_SYSMENU, $WS_MINIMIZEBOX, $WS_MAXIMIZEBOX, $WS_SIZEBOX))
; Höhe und Breite in den Grenzen änderbar
_GuiMinMax($hGui, 200, 150, 800, 500)
; nur Höhe änderbar (min: 150, max: ohne Limit)
; !!! Wird Breite oder Höhe in Min auf "-1" gesetzt MUSS der korrespondierende Wert in Max auch "-1" sein. Sonst Änderung nur einmalig.
;~ _GuiMinMax($hGui, -1, 150, -1, 0) ; "0": keine Limitierung, "-1": keine Größenänderung möglich!
; nur Breite änderbar (min: 200, max: 900)
;~ _GuiMinMax($hGui, 200, -1, 900, -1)
GUISetState()
While True
Switch GUIGetMsg()
Case -3
Exit
EndSwitch
WEnd
; --------------------------------------------------------------------------------------------------
Func _GuiMinMax($_hWnd, $_wMin=-1, $_hMin=-1, $_wMax=-1, $_hMax=-1)
_SizeHook($_hWnd)
Local $index = -1
For $i = 1 To $g_aWnd[0][0]
If $g_aWnd[$i][0] = $_hWnd Then
$index = $i
ExitLoop
EndIf
Next
If $index = -1 Then Return
If $_wMin > -1 Then $g_aWnd[$index][1] = $_wMin
If $_hMin > -1 Then $g_aWnd[$index][2] = $_hMin
If $_wMax > -1 Then $g_aWnd[$index][3] = $_wMax
If $_hMax > -1 Then $g_aWnd[$index][4] = $_hMax
EndFunc
Func _SizeHook($_hWnd)
If $g_aWnd[0][0] = UBound($g_aWnd) -1 Then ReDim $g_aWnd[UBound($g_aWnd) +100][5]
For $i = 1 To $g_aWnd[0][0]
If $g_aWnd[$i][0] = $_hwnd Then Return
Next
$g_aWnd[0][0] += 1
$g_aWnd[$g_aWnd[0][0]][0] = $_hWnd
$g_aWnd[$g_aWnd[0][0]][1] = -1
$g_aWnd[$g_aWnd[0][0]][2] = -1
$g_aWnd[$g_aWnd[0][0]][3] = -1
$g_aWnd[$g_aWnd[0][0]][4] = -1
If $g_hSizeProc = Null Then $g_hSizeProc = DllCallbackRegister('_SizeWindowProc', 'ptr', 'hwnd;uint;wparam;lparam')
$g_hSizeHook = _WinAPI_SetWindowLong($_hWnd, $GWL_WNDPROC, DllCallbackGetPtr($g_hSizeProc))
EndFunc
Func _HookCleanUp()
If $g_hSizeProc = Null Then Return
Local $hWnd
For $i = 1 To $g_aWnd[0][0] ; reset to default window procedure
If WinExists($g_aWnd[$i][0]) Then _WinAPI_SetWindowLong($g_aWnd[$i][0], $GWL_WNDPROC, $g_hSizeHook)
Next
DllCallbackFree($g_hSizeProc)
EndFunc
Func _SizeWindowProc($_hWnd, $_iMsg, $_iwParam, $_ilParam)
If ($_iMsg <> $WM_SYSCOMMAND And _ ; A window receives this message when the user ... or when the user chooses the maximize button, minimize button, restore button, or close button.
$_iMsg <> $WM_WINDOWPOSCHANGING And _ ; Sent to a window whose size, position, or place in the Z order is about to change
$_iMsg <> $WM_NCLBUTTONDBLCLK) Then _ ; Posted when the user double-clicks the left mouse button while the cursor is within the nonclient area of a window.
Return _WinAPI_CallWindowProc($g_hSizeHook, $_hWnd, $_iMsg, $_iwParam, $_ilParam)
Local $index = -1
For $i = 1 To $g_aWnd[0][0]
If $g_aWnd[$i][0] = $_hWnd Then
$index = $i
ExitLoop
EndIf
Next
If $index = -1 Then Return _WinAPI_CallWindowProc($g_hSizeHook, $_hWnd, $_iMsg, $_iwParam, $_ilParam) ; default window processing
Local $tRectWnd = _WinAPI_GetWindowRect($_hWnd)
Local $iW_Wnd = $tRectWnd.Right - $tRectWnd.Left
Local $iH_Wnd = $tRectWnd.Bottom - $tRectWnd.Top
Local $iX_Wnd = $tRectWnd.Left
Local $iY_Wnd = $tRectWnd.Top
Local $wMin = $g_aWnd[$index][1]
Local $hMin = $g_aWnd[$index][2]
Local $wMax = $g_aWnd[$index][3]
Local $hMax = $g_aWnd[$index][4]
If $_iMsg = $WM_WINDOWPOSCHANGING Then
Local $tWINDOWPOS = DllStructCreate("struct; HWND hwndInsertAfter;HWND hwnd;INT x;INT y;INT cx;INT cy;UINT flags; endstruct", $_ilParam)
If $tWINDOWPOS.cx < $wMin Then ; target width too small
$tWINDOWPOS.cx = $wMin ; set to min
$tWINDOWPOS.x = $iX_Wnd ; keep the current x value
EndIf
If $tWINDOWPOS.cy < $hMin Then ; target height too small
$tWINDOWPOS.cy = $hMin ; set to min
$tWINDOWPOS.y = $iY_Wnd ; keep the current y value
EndIf
If $tWINDOWPOS.cx > $wMax Then ; target width too large
$tWINDOWPOS.cx = $wMax ; set to max
$tWINDOWPOS.x = $iX_Wnd ; keep the current x value
EndIf
If $tWINDOWPOS.cy > $hMax Then ; target height too large
$tWINDOWPOS.cy = $hMax ; set to max
$tWINDOWPOS.y = $iY_Wnd ; keep the current y value
EndIf
Return 0 ; avoid default window processing
ElseIf $_iMsg = $WM_NCLBUTTONDBLCLK And $_iwParam = $HTCAPTION Then ; DBLCLICK on title bar, default: maximize window
If $wMax > -1 Or $hMax > -1 Then ; a max value is set, resize the window to this value
; resize to max
WinMove($_hWnd, '', $iX_Wnd, $iY_Wnd, ($wMax > -1 ? $wMax : $iW_Wnd), ($hMax > -1 ? $hMax : $iH_Wnd))
Return 0 ; avoid default window processing
Else ; allow default window processing
Return _WinAPI_CallWindowProc($g_hSizeHook, $_hWnd, $_iMsg, $_iwParam, $_ilParam)
EndIf
Else ; WM_SYSCOMMAND
; if min/max is set (> -1): minimize/maximize only by this values
Switch $_iwParam
Case $SC_MINIMIZE ; default processing
;
Case $SC_MAXIMIZE
If $wMax > -1 Or $hMax > -1 Then
WinMove($_hWnd, '', $iX_Wnd, $iY_Wnd, ($wMax > -1 ? $wMax : $iW_Wnd), ($hMax > -1 ? $hMax : $iH_Wnd))
Return 0 ; avoid default window processing
EndIf
EndSwitch
EndIf
Return _WinAPI_CallWindowProc($g_hSizeHook, $_hWnd, $_iMsg, $_iwParam, $_ilParam) ; default Window processing
EndFunc
Alles anzeigen
steht etwas von einem Event für WinProc (SC_MOVE),
Im Moment lasse ich WM_GETMINMAXINFO aussen vor, wo das evtl. den Positionssprung anzeigen könnte. Vielleicht komme ich nochmal drauf zurück.
Falls dein Fenster also keine Menuzeile hat (die ist sonst ganz oben, wobeeeeei, die kann man doch bestimmt als Pseudotitelleiste missbrauchen, wenn man ihren Grafikpuffer geschickt übermalt :D), kannst du via WS_POPUP ein "nacktes" Fenster erzeugen und die von dir gewünschten zulässigen Events (Resize wenn der User es will, Minimieren, Maximieren, Exit, Verschieben, etc) manuell verarbeiten.
Mein Ziel ist kein individuelles Fenster, sondern geplant ist eine Anwendung für beliebige Fenster.
die WM_MOVING wird beim ziehen der Titelleiste gesendet
Ja, auch das muss überwacht werden mit entsprechender Kollision am Bildschirmrand.
Die WM_SIZING wird nur gesendet, wenn der Rahmen gezogen wird, bzw. die Größe geändert wird.
Das ist wesentlicher Bestandteil, da es in meinem geplanten Projekt ein möglicher Style des genutzten Fensters ist. Somit möchte ich da auch volle Funktionalität haben.
WM_WINDOWPOSCHANGING
Das scheint wohl die sinnvollste Variante zu sein, um einen Kollisionscheck (mit Bildschirmrand) dauerhaft zu implementieren..
Ich habe in Post 1 eine Kurzversion eines Skriptes gestellt, dass mein Vorgehen zeigt.
Ich würde die Minimale/Maximale größe des Fensters mit WM_GETMINMAXINFO begrenzen.
Das schaut schonmal ganz gut aus. Da muss ich jetzt nur noch eine Änderung der Position verhindern. Momentan springt das Fenster an den Wert, den es hätte - aber aufgrund der unterdrückten Größenänderung nicht einnehmen darf.
Schau mal hier: https://www.windows-faq.de/2019/02/05/aut…bei-windows-10/
Naja, ist eine Windowseinstellung. Das ist in einem Programm nicht von Nutzen.
Wenn du manuell die entsprechenden Mouse-Events abfängst, solltest du evtl. beachten, dass man den gleichen Effekt mit den Tastenkombinationen Win+Pfeiltaste ebenfalls erreicht. Ein reines Abfragen von Mouse-Events könnte also je nach genauer Zielstellung nicht ausreichen.
Ja, leider. Windows weist da keinerlei Konsistenz auf. Eigentlich könnte man erwarten, dass ein gleiches Ergebnis auch eine identisch WM_ als Basis hat. Aber leider....
Bill Gates wird sicher sagen: It's not a bug - it's a feature.
Das hast du falsch verstanden. Normale Größenänderung ist selbstverständlich erlaubt.
Ich verwalte die Fenster und Messages sowieso in eigener Window-Procedure. Ich möchte aber die 3 oben genannten Ereignisse verhindern. Auf Danach-Events zuzugreifen ist auch kein guter Weg. Die von mir erlaubte Größenänderung in gesetzten Grenzen (minSize, maxSize) beeinflusse ich bevor sie passiert (WM_SIZING).
Denn wenn ich für ein Fenster eine maximale Größe definiere, ist ein Maximize fehl am Platz, ebenso die Änderung auf halben Bildschirm oder volle Höhe.
Hi,
ich möchte verhindern, dass ein Fenster seine Größe ändert bei folgenden Aktionen:
Leider friert mein Winspector Spy beim Loggen von Messages ein, sodass ich das nicht nachverfolgen kann.
Ich habe getestet, ob es eine Kombination mit WM_NCLBUTTONDOWN ist. Dass die Maustaste gedrückt ist am Fensterrand (zum Ziehen) kann ich damit auch erkennen. Nun fehlt mir aber der nächste Schritt. Die oben angeführten Ereignisse treten ja erst auf, wenn mit der gezogenen Maus der Bildschirmrand berührt wird. Ich kann mir nicht vorstellen, dass ich hier permanent berechnen muss, ob Mausposition mit Bildschirmrand übereinstimmt. Da sollte doch eigentlich eine Nachricht gesendet werden mit den Infos: Mouse hold-down moved-to Border (links,rechts,oben,unten).
Bin für Anregungen dankbar.
EDIT:
Ich habe mal aus meinem Projekt den Code in ein einzelnes minimales Skript gezogen, zum besseren Verständnis:
;-- TIME_STAMP 2020-11-08 13:54:24
#include <GUIConstantsEx.au3>
#include <WinAPISysWin.au3>
#include <WinAPIConv.au3>
#include <WindowsConstants.au3>
Opt('MustDeclareVars', 1)
OnAutoItExitRegister("_HookCleanUp")
Global Const $WMSZ_BOTTOM = 6 ; Bottom edge
Global Const $WMSZ_BOTTOMLEFT = 7 ; Bottom-left corner
Global Const $WMSZ_BOTTOMRIGHT = 8 ; Bottom-right corner
Global Const $WMSZ_LEFT = 1 ; Left edge
Global Const $WMSZ_RIGHT = 2 ; Right edge
Global Const $WMSZ_TOP = 3 ; Top edge
Global Const $WMSZ_TOPLEFT = 4 ; Top-left corner
Global Const $WMSZ_TOPRIGHT = 5 ; Top-right corner
Global Const $SC_MOVE = 0xF010
Global Const $SC_MINIMIZE = 0xF020
Global Const $SC_MAXIMIZE = 0xF030
Global $g_hSizeHook, $g_hSizeProc = Null
Global $g_aWnd[100][5] = [[0]] ; [[counter],[hWnd,widthMin,heightMin,widthMax,heightMax], ..]
; --------------------------------------------------------------------------------------------------
Global $hGui = GUICreate('Sizing', 400, 300, -1, -1, BitOR($WS_SYSMENU, $WS_MINIMIZEBOX, $WS_MAXIMIZEBOX, $WS_SIZEBOX))
; Höhe und Breite in den Grenzen änderbar
_GuiMinMax($hGui, 200, 150, 800, 500)
; nur Höhe änderbar (min: 150, max: ohne Limit)
; !!! Wird Breite oder Höhe in Min auf "-1" gesetzt MUSS der korrespondierende Wert in Max auch "-1" sein. Sonst Änderung nur einmalig.
;~ _GuiMinMax($hGui, -1, 150, -1, 0) ; "0": keine Limitierung, "-1": keine Größenänderung möglich!
; nur Breite änderbar (min: 150, max: 900)
;~ _GuiMinMax($hGui, 200, -1, 900, -1)
GUISetState()
While True
Switch GUIGetMsg()
Case -3
Exit
EndSwitch
WEnd
; --------------------------------------------------------------------------------------------------
Func _GuiMinMax($_hWnd, $_wMin=-1, $_hMin=-1, $_wMax=-1, $_hMax=-1)
_SizeHook($_hWnd)
Local $index = -1
For $i = 1 To $g_aWnd[0][0]
If $g_aWnd[$i][0] = $_hWnd Then
$index = $i
ExitLoop
EndIf
Next
If $index = -1 Then Return
If $_wMin > -1 Then $g_aWnd[$index][1] = $_wMin
If $_hMin > -1 Then $g_aWnd[$index][2] = $_hMin
If $_wMax > -1 Then $g_aWnd[$index][3] = $_wMax
If $_hMax > -1 Then $g_aWnd[$index][4] = $_hMax
EndFunc
Func _SizeHook($_hWnd)
If $g_aWnd[0][0] = UBound($g_aWnd) -1 Then ReDim $g_aWnd[UBound($g_aWnd) +100][5]
For $i = 1 To $g_aWnd[0][0]
If $g_aWnd[$i][0] = $_hwnd Then Return
Next
$g_aWnd[0][0] += 1
$g_aWnd[$g_aWnd[0][0]][0] = $_hWnd
$g_aWnd[$g_aWnd[0][0]][1] = -1
$g_aWnd[$g_aWnd[0][0]][2] = -1
$g_aWnd[$g_aWnd[0][0]][3] = -1
$g_aWnd[$g_aWnd[0][0]][4] = -1
If $g_hSizeProc = Null Then $g_hSizeProc = DllCallbackRegister('_SizeWindowProc', 'ptr', 'hwnd;uint;wparam;lparam')
$g_hSizeHook = _WinAPI_SetWindowLong($_hWnd, $GWL_WNDPROC, DllCallbackGetPtr($g_hSizeProc))
EndFunc
Func _HookCleanUp()
If $g_hSizeProc = Null Then Return
For $i = 1 To $g_aWnd[0][0] ; reset to default window procedure
If WinExists($g_aWnd[$i][0]) Then _WinAPI_SetWindowLong($g_aWnd[$i][0], $GWL_WNDPROC, $g_hSizeHook)
Next
DllCallbackFree($g_hSizeProc)
EndFunc
Func _SizeWindowProc($_hWnd, $_iMsg, $_iwParam, $_ilParam)
If ($_iMsg <> $WM_SIZING And _ ; Sent to a window that the user is resizing.
$_iMsg <> $WM_SYSCOMMAND And _ ; A window receives this message when the user ... or when the user chooses the maximize button, minimize button, restore button, or close button.
$_iMsg <> $WM_NCLBUTTONDBLCLK) Then _ ; Posted when the user double-clicks the left mouse button while the cursor is within the nonclient area of a window.
Return _WinAPI_CallWindowProc($g_hSizeHook, $_hWnd, $_iMsg, $_iwParam, $_ilParam)
Local $index = -1
For $i = 1 To $g_aWnd[0][0]
If $g_aWnd[$i][0] = $_hWnd Then
$index = $i
ExitLoop
EndIf
Next
If $index = -1 Then Return _WinAPI_CallWindowProc($g_hSizeHook, $_hWnd, $_iMsg, $_iwParam, $_ilParam) ; default window processing
Local $iW_Wnd = _WinAPI_GetWindowWidth($_hWnd), $iH_Wnd = _WinAPI_GetWindowHeight($_hWnd)
Local $wMin = $g_aWnd[$index][1]
Local $hMin = $g_aWnd[$index][2]
Local $wMax = $g_aWnd[$index][3]
Local $hMax = $g_aWnd[$index][4]
If $_iMsg = $WM_SIZING Then ; message before the size will changed
Local $tRect = DllStructCreate("struct; long Left;long Top;long Right;long Bottom; endstruct", $_ilParam)
Local $iW = $tRect.Right - $tRect.Left
Local $iH = $tRect.Bottom - $tRect.Top
$wMin = $wMin = 0 ? $iW : ($wMin = -1 ? $iW_Wnd : $wMin) ; "0": free sizeable, "-1": no sizeable in this direction, otherwise the min value
$hMin = $hMin = 0 ? $iH : ($hMin = -1 ? $iH_Wnd : $hMin)
$wMax = $wMax = 0 ? $iW : ($wMax = -1 ? $iW_Wnd : $wMax) ; "0": free sizeable, "-1": no sizeable in this direction, otherwise the max value
$hMax = $hMax = 0 ? $iH : ($hMax = -1 ? $iH_Wnd : $hMax)
Local $bCorrect_wMin = ($iW < $wMin) ; True: set $tRect.Left & $tRect.Right to $wMin related by starting point of sizing ($_iwParam)
Local $bCorrect_hMin = ($iH < $hMin) ; True: set $tRect.Bottom & $tRect.Top to $hMin related by starting point of sizing ($_iwParam)
Local $bCorrect_wMax = ($iW > $wMax) ; True: set $tRect.Left & $tRect.Right to $wMax related by starting point of sizing ($_iwParam)
Local $bCorrect_hMax = ($iH > $hMax) ; True: set $tRect.Bottom & $tRect.Top to $hMax related by starting point of sizing ($_iwParam)
Switch $_iwParam ; The edge of the window that is being sized.
Case $WMSZ_BOTTOM ; Bottom edge changing height by $tRect.Bottom
If $bCorrect_hMin Then $tRect.Bottom = $tRect.Top + $hMin
If $bCorrect_hMax Then $tRect.Bottom = $tRect.Top + $hMax
Case $WMSZ_BOTTOMLEFT ; Bottom-left corner changing height and/or width by $tRect.Bottom and/or $tRect.Left
If $bCorrect_hMin Then $tRect.Bottom = $tRect.Top + $hMin
If $bCorrect_hMax Then $tRect.Bottom = $tRect.Top + $hMax
If $bCorrect_wMin Then $tRect.Left = $tRect.Right - $wMin
If $bCorrect_wMax Then $tRect.Left = $tRect.Right - $wMax
Case $WMSZ_BOTTOMRIGHT ; Bottom-right corner changing height and/or width by $tRect.Bottom and/or $tRect.Right
If $bCorrect_hMin Then $tRect.Bottom = $tRect.Top + $hMin
If $bCorrect_hMax Then $tRect.Bottom = $tRect.Top + $hMax
If $bCorrect_wMin Then $tRect.Right = $tRect.Left + $wMin
If $bCorrect_wMax Then $tRect.Right = $tRect.Left + $wMax
Case $WMSZ_LEFT ; Left edge changing width by $tRect.Left
If $bCorrect_wMin Then $tRect.Left = $tRect.Right - $wMin
If $bCorrect_wMax Then $tRect.Left = $tRect.Right - $wMax
Case $WMSZ_RIGHT ; Right edge changing width by $tRect.Right
If $bCorrect_wMin Then $tRect.Right = $tRect.Left + $wMin
If $bCorrect_wMax Then $tRect.Right = $tRect.Left + $wMax
Case $WMSZ_TOP ; Top edge changing height by $tRect.Top
If $bCorrect_hMin Then $tRect.Top = $tRect.Bottom - $hMin
If $bCorrect_hMax Then $tRect.Top = $tRect.Bottom - $hMax
Case $WMSZ_TOPLEFT ; Top-left corner changing height and/or width by $tRect.Top and/or $tRect.Left
If $bCorrect_hMin Then $tRect.Top = $tRect.Bottom - $hMin
If $bCorrect_hMax Then $tRect.Top = $tRect.Bottom - $hMax
If $bCorrect_wMin Then $tRect.Left = $tRect.Right - $wMin
If $bCorrect_wMax Then $tRect.Left = $tRect.Right - $wMax
Case $WMSZ_TOPRIGHT ; Top-right corner changing height and/or width by $tRect.Top and/or $tRect.Right
If $bCorrect_hMin Then $tRect.Top = $tRect.Bottom - $hMin
If $bCorrect_hMax Then $tRect.Top = $tRect.Bottom - $hMax
If $bCorrect_wMin Then $tRect.Right = $tRect.Left + $wMin
If $bCorrect_wMax Then $tRect.Right = $tRect.Left + $wMax
EndSwitch
ElseIf $_iMsg = $WM_NCLBUTTONDBLCLK And $_iwParam = $HTCAPTION Then ; DBLCLICK on title bar, default: maximize window
Local $aWin = WinGetPos($_hWnd)
If $wMax > -1 Or $hMax > -1 Then ; a max value is set, resize the window to this value
; resize to max
WinMove($_hWnd, '', $aWin[0], $aWin[1], ($wMax > -1 ? $wMax : $aWin[2]), ($hMax > -1 ? $hMax : $aWin[3]))
Return 0 ; avoid default window processing
Else ; allow default window processing
Return _WinAPI_CallWindowProc($g_hSizeHook, $_hWnd, $_iMsg, $_iwParam, $_ilParam)
EndIf
Else ; WM_SYSCOMMAND
; if min/max is set (> -1): minimize/maximize only by this values
Local $aWin = WinGetPos($_hWnd)
Switch $_iwParam
Case $SC_MINIMIZE ; default processing
;
Case $SC_MAXIMIZE
If $wMax > -1 Or $hMax > -1 Then
WinMove($_hWnd, '', $aWin[0], $aWin[1], ($wMax > -1 ? $wMax : $aWin[2]), ($hMax > -1 ? $hMax : $aWin[3]))
Return 0 ; avoid default Window processing
EndIf
EndSwitch
EndIf
Return _WinAPI_CallWindowProc($g_hSizeHook, $_hWnd, $_iMsg, $_iwParam, $_ilParam) ; default Window processing
EndFunc
Alles anzeigen
Für normale Sachen nehme ich üblicherweise Sublime.
Wenn du damit vertraut bist kannst du es auch für AutoIt anwenden: AutoIt mit Sublime Text 2/3 -- Sprachdef. f. Stable v3.3.12.0, Wrapper, Au3Check, Run m. Parameter
.. und im englischen Forum: https://www.autoitscript.com/forum/topic/148016-sublimetext/