Posts: 36
Threads: 21
Joined: Mar 2022
Hello, I have a few questions, is there an LA alternative to CaptureWindowAndRect from QM?
I am still very new to C# and was going through the LA source code and noticed that some LA windows are created using wpfbuilder, why do these windows open instantly? I have a couple of small projects using wpfbuilder, and sometimes they take up to 6 seconds to open.
Posts: 12,071
Threads: 140
Joined: Dec 2002
// script ""
//if (!Capture.WindowAndRect(out var r, CWRNeed.Window, true)) return;
//if (!Capture.WindowAndRect(out var r, CWRNeed.Window, false)) return;
//if (!Capture.WindowAndRect(out var r, CWRNeed.Rect)) return;
//if (!Capture.WindowAndRect(out var r, CWRNeed.WindowAndRect, true)) return;
//if (!Capture.WindowAndRect(out var r, CWRNeed.WindowAndRect, false)) return;
if (!Capture.WindowAndRect(out var r, CWRNeed.WindowOrRect, true)) return;
//if (!Capture.WindowAndRect(out var r, CWRNeed.WindowOrRect, false)) return;
print.it(r);
/// <summary>
/// Helps to capture various objects on screen.
/// </summary>
public static class Capture {
/// <summary>
/// Waits for Shift key and then captures a window or/and rectangle on screen.
/// </summary>
/// <returns>true if captured, false if pressed Esc.</returns>
/// <param name="results"></param>
/// <param name="need"></param>
/// <param name="rectInClient">Get rectangle in window client area.</param>
/// <param name="wxyFlags"></param>
public static bool WindowAndRect(out CWRResults results, CWRNeed need, bool rectInClient = false, WXYFlags wxyFlags = 0) {
results = default;
var s = need switch {
CWRNeed.Window => "Press Shift to capture window or control.",
CWRNeed.Rect => "Shift+mouse move to capture rectangle on screen.",
CWRNeed.WindowAndRect => "Shift+mouse move to capture rectangle in a window or control.",
_ => "Press Shift to capture window or control.\nOr Shift+mouse move to capture rectangle in a window or control."
};
s += "\nOr press Esc to cancel.";
using var osd = osdText.showText(s, -1);
wnd w = default, wMain = default;
bool needWindow = need != CWRNeed.Rect;
if (needWindow) {
using var osrw = new osdRect { };
osrw.Show();
for (; ; ) {
wait.doEvents(12);
if (keys.isPressed(KKey.Escape)) return false;
w = wnd.fromMouse(wxyFlags);
osrw.Rect = w.Rect;
if (keys.isShift) break;
}
} else {
for (; ; ) {
wait.doEvents(12);
if (keys.isPressed(KKey.Escape)) return false;
if (keys.isShift) break;
}
}
var p = mouse.xy;
RECT r = new(p.x, p.y, 0, 0);
if (need != CWRNeed.Window) {
if (needWindow) {
wMain = w.Window;
var rw = rectInClient ? wMain.ClientRectInScreen : wMain.Rect;
unsafe { api.ClipCursor(&rw); }
}
try {
//using var osrr = new osdRect { Color = 0xff, Opacity = .5, Rect = r };
using var osrr = new osdRect { Color = 0xff0000, Thickness = 1, Rect = r };
osrr.Show();
for (var r1 = r; ;) {
wait.doEvents(12);
if (keys.isPressed(KKey.Escape)) return false;
if (!keys.isShift) break;
p = mouse.xy;
r1.right = p.x; r1.bottom = p.y;
r = r1; r.Normalize(true);
osrr.Rect = r;
}
}
finally { if (needWindow) unsafe { api.ClipCursor(null); } }
if (needWindow && w != wMain) { //if rect spans multiple controls, get top-level window
var w2 = wnd.fromMouse(wxyFlags);
if (w2 != w) w = wMain;
}
}
if (needWindow && rectInClient) w.MapScreenToClient(ref r);
results = new(w, !r.NoArea, r);
return true;
}
unsafe class api : NativeApi {
[DllImport("user32.dll")]
internal static extern bool ClipCursor(RECT* lpRect);
}
}
/// <summary>
/// Used with <see cref="Capture.WindowAndRect"/>.
/// </summary>
public enum CWRNeed {
/// <summary>Need only window.</summary>
Window,
/// <summary>Need only rectangle.</summary>
Rect,
/// <summary>Need rectangle in window.</summary>
WindowAndRect,
/// <summary>Need window and optionally rectangle in it.</summary>
WindowOrRect
}
/// <summary>
/// Used with <see cref="Capture.WindowAndRect"/>.
/// </summary>
public record struct CWRResults(wnd w, bool hasRect, RECT r);
Posts: 12,071
Threads: 140
Joined: Dec 2002
12-11-2022, 12:17 PM
(This post was last modified: 12-11-2022, 12:35 PM by Gintaras.)
WPF starts slowly. Only the first WPF window in that process; other windows are faster. On most computers the first window should start in less than 1 s.
// script ""
using System.Windows;
using System.Windows.Controls;
//This script measures the time needed to show a WPF window.
for (int i = 0; i < 2; i++) {
perf.first();
timer.after(1, _ => { perf.nw(); }); //when the window is fully loaded, visible and ready for input
ShowWpfWindow();
1.s();
}
void ShowWpfWindow() {
var w = new Window { Title = "WPF window" };
w.Content = new TextBox();
w.ShowDialog();
}
//On my new Win11 computer: first time 300 ms, then 45 ms.
//On my old (year 2014) Win10 computer: first time 600 ms, then 50 ms. After long time first time can be 1.8 s.
Posts: 36
Threads: 21
Joined: Mar 2022
Thanks it worked great, your test script ran normally, I think some nuget package is making the startup slow, as always thanks for the help.