надоело каждый раз при запуске окон двигать их руками в 21м веке, в разгар ИИ и прочих историй, поэтому решил поинтересоваться у знающих на форуме (те, кто на атомы расщепил клиент) где это можно исполнить, но пока только рекомендации в совсем другую степь (напиши доп. утилю/а зачем? и т.д.)Больше интересно для чего это нужно) будто религия не позволяет самому перетащить окно))))
только рулону не говорипуть пользователей IL - путь страданий
путь пользователей IL - путь страданий
Спасибо большое за уточнение! Попробовал в Interlude добавить их - не сработало, вероятно в IL такого нетНет, за размер отвечают GamePlayViewportX и GamePlayViewportY там же.
На ИТ этот файл есть, но он отвечает за внутриигровые окна, а человеку из темы надо чтобы само окно л2 открывалось в нужном месте.Я хз, есть ли в дефолтном патче ИЛ файл WindowsInfo.ini? На ХФ вроде инфа о положении окон в нем хранится, если я ничего не путаю.
Спасибо, в глаза долблюсь. Прочитал первое сообщение не внимательно(На ИТ этот файл есть, но он отвечает за внутриигровые окна, а человеку из темы надо чтобы само окно л2 открывалось в нужном месте.
Как нет, есть в файле Option.iniСпасибо большое за уточнение! Попробовал в Interlude добавить их - не сработало, вероятно в IL такого нет
Это "разрешение экрана", а не расположение окна.Как нет, есть в файле Option.ini
Раздел
[Video]
GamePlayViewportX=1024 тут выставляешь разрешения своего экрана.
GamePlayViewportY=768
ну как там получается через *.ini? теперь понял к чему это ?Прошу простить меня, но не совсем понял к чему это. Писать отдельную утилю для перемещения окна л2? это не совсем то, чем хотелось бы заниматься, интересует именно расположение где хранится по-молчанию позиция окна l2 при запуске (ведь наверняка он берет её из ini).
Посмотреть как работает тот самый лаунчер нет возможности?При этом если запускать клиент сторонним лаунчером (например l2alone), то этот лаунтчер имеет такую фичу - запускать клиент с определенной позицией (вероятно лаунчер передает какие-то флаги клиенту при запуске).
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
namespace L2
{
class Program
{
static void Main(string[] args)
{
var fileName = "l2.bin";
if (!File.Exists(fileName))
{
MessageBox(IntPtr.Zero, $"File {fileName} not found!", "Warning!", MB_ICONWARNING);
return;
}
try
{
var process = new Process
{
StartInfo = new ProcessStartInfo(fileName)
{
UseShellExecute = false
}
};
process.Start();
var splashWindowHandler = IntPtr.Zero;
// Waiting for splash window handler
do
{
process.Refresh();
splashWindowHandler = process.MainWindowHandle;
}
while (splashWindowHandler == IntPtr.Zero);
var mainWindowHandler = IntPtr.Zero;
// Waiting for main window handler
do
{
process.Refresh();
if (splashWindowHandler != process.MainWindowHandle)
{
mainWindowHandler = process.MainWindowHandle;
}
}
while (mainWindowHandler == IntPtr.Zero);
if (!GetWindowRect(mainWindowHandler, out var mainWindowRect))
{
MessageBox(IntPtr.Zero, "Error: 0x" + GetLastError().ToString("X"), "GetWindowRect(Main Window)", MB_ICONWARNING));
return;
}
var windowWidth = mainWindowRect.right - mainWindowRect.left;
var windowHeight = mainWindowRect.bottom - mainWindowRect.top;
GetWindowRect(GetDesktopWindow(), out var desktopWindowRect);
var screenWidth = desktopWindowRect.right - desktopWindowRect.left;
var screenHeight = desktopWindowRect.bottom - desktopWindowRect.top;
var isFullscreen = windowWidth == screenWidth && windowHeight == screenHeight;
if (!isFullscreen)
{
// TODO: SetWindowPos???
var moveWindowResult = MoveWindow(
mainWindowHandler,
GetSystemMetrics(SM_CXSCREEN) / 2 - windowWidth / 2,
GetSystemMetrics(SM_CYSCREEN) / 2 - windowHeight / 2,
windowWidth,
windowHeight,
true);
if (!moveWindowResult)
{
MessageBox(IntPtr.Zero, "Error: 0x" + GetLastError().ToString("X"), "MoveWindow", MB_ICONWARNING));
}
}
}
catch (Exception e)
{
MessageBox(IntPtr.Zero, e.ToString(), e.Message, MB_ICONWARNING));
}
}
// https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getsystemmetrics
public static readonly int SM_CXSCREEN = 0;
public static readonly int SM_CYSCREEN = 1;
// https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messagebox
public static readonly long MB_ICONWARNING = 0x00000030L;
// https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messagebox
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int MessageBox(IntPtr hWnd, string lpText, string lpCaption, long uType);
// https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowrect
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
// https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdesktopwindow
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr GetDesktopWindow();
// https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getsystemmetrics
[DllImport("user32.dll")]
public static extern int GetSystemMetrics(int nIndex);
// https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-movewindow
[DllImport("user32.dll", SetLastError = true)]
public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
[DllImport("kernel32.dll")]
public static extern uint GetLastError();
// https://learn.microsoft.com/en-us/windows/win32/api/windef/ns-windef-rect
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
}
}
}
Посмотреть как работает тот самый лаунчер нет возможности?
В любом случает вот вариант позиционирования окна клиента (в данном примере по центру). По сути запускает основной процесс l2.exe, переименованный в l2.bin. Запустив процесс, программа ждет пока не станет доступен указатель на основное окно клиента. Получив указатель на окно, за счет нативным методов делает расчеты и перемещает окно по центру.
C#:using System; using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; namespace L2 { class Program { static void Main(string[] args) { var fileName = "l2.bin"; if (!File.Exists(fileName)) { MessageBox(IntPtr.Zero, $"File {fileName} not found!", "Warning!", MB_ICONWARNING); return; } try { var process = new Process { StartInfo = new ProcessStartInfo(fileName) { UseShellExecute = false } }; process.Start(); var splashWindowHandler = IntPtr.Zero; // Waiting for splash window handler do { process.Refresh(); splashWindowHandler = process.MainWindowHandle; } while (splashWindowHandler == IntPtr.Zero); var mainWindowHandler = IntPtr.Zero; // Waiting for main window handler do { process.Refresh(); if (splashWindowHandler != process.MainWindowHandle) { mainWindowHandler = process.MainWindowHandle; } } while (mainWindowHandler == IntPtr.Zero); if (!GetWindowRect(mainWindowHandler, out var mainWindowRect)) { MessageBox(IntPtr.Zero, "Error: 0x" + GetLastError().ToString("X"), "GetWindowRect(Main Window)", MB_ICONWARNING)); return; } var windowWidth = mainWindowRect.right - mainWindowRect.left; var windowHeight = mainWindowRect.bottom - mainWindowRect.top; GetWindowRect(GetDesktopWindow(), out var desktopWindowRect); var screenWidth = desktopWindowRect.right - desktopWindowRect.left; var screenHeight = desktopWindowRect.bottom - desktopWindowRect.top; var isFullscreen = windowWidth == screenWidth && windowHeight == screenHeight; if (!isFullscreen) { // TODO: SetWindowPos??? var moveWindowResult = MoveWindow( mainWindowHandler, GetSystemMetrics(SM_CXSCREEN) / 2 - windowWidth / 2, GetSystemMetrics(SM_CYSCREEN) / 2 - windowHeight / 2, windowWidth, windowHeight, true); if (!moveWindowResult) { MessageBox(IntPtr.Zero, "Error: 0x" + GetLastError().ToString("X"), "MoveWindow", MB_ICONWARNING)); } } } catch (Exception e) { MessageBox(IntPtr.Zero, e.ToString(), e.Message, MB_ICONWARNING)); } } // https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getsystemmetrics public static readonly int SM_CXSCREEN = 0; public static readonly int SM_CYSCREEN = 1; // https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messagebox public static readonly long MB_ICONWARNING = 0x00000030L; // https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messagebox [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern int MessageBox(IntPtr hWnd, string lpText, string lpCaption, long uType); // https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowrect [DllImport("user32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect); // https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdesktopwindow [DllImport("user32.dll", SetLastError = true)] public static extern IntPtr GetDesktopWindow(); // https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getsystemmetrics [DllImport("user32.dll")] public static extern int GetSystemMetrics(int nIndex); // https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-movewindow [DllImport("user32.dll", SetLastError = true)] public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint); [DllImport("kernel32.dll")] public static extern uint GetLastError(); // https://learn.microsoft.com/en-us/windows/win32/api/windef/ns-windef-rect public struct RECT { public int left; public int top; public int right; public int bottom; } } }
Сам проект на .NET Framework 2.0 (исходы и компил прикрепил)
никак, поскольку и не запоминает. Да и зачем, если задача текущего кода запускать/корректировать окно по центру.а как в таком запуске происходит процесс запоминания изменений окна?
хм, а отслеживать чужое окно скорее всего и не получится, по крайне мере у меня не получилось через SetWindowLong с флагом GWL_WNDPROC. Может как можно повесть слушателя WndProc через ChangeWindowMessageFilter(Ex). Будет еще время и желание, потыкаю. Но пока судя по всему работать с окном, которое мы не создавали из текущего процесса, попросту нельзя.допустим после некоторого запуска человек меняет положение левого верхнего края окна и его размер перед закрытием. по коду я так понял она не отслеживает этого и надо дописывать?
Все верно, по завершению манипуляций с окном процесс закрывается.И я правильно понял, что этот "запускатель" выключается после выполненой задачи центрирования запущенного окна ЛА2?
никак, поскольку и не запоминает. Да и зачем, если задача текущего кода запускать/корректировать окно по центру.
хм, а отслеживать чужое окно скорее всего и не получится, по крайне мере у меня не получилось через SetWindowLong с флагом GWL_WNDPROC. Может как можно повесть слушателя WndProc через ChangeWindowMessageFilter(Ex). Будет еще время и желание, потыкаю. Но пока судя по всему работать с окном, которое мы не создавали из текущей процесса, попросту нельзя.
Все верно, по завершению манипуляций с окном процесс закрывается.
ну размеры то и так запоминает, на клиенте интерлюда который мне попался под рукупрошлые размеры и положение
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?