Позиция окна при запуске клиента?

Neo`

Последний из атеистов
Участник
Сообщения
41
Розыгрыши
0
Репутация
0
Реакции
23
Баллы
845
Добрый день! Прошу вашей помощи, излазил все *.ini и так и не смог найти и понять можно ли как-то настроить координаты для того, чтобы клиент запускался всегда в одной позиции окна (находил параметр WindowPosition в l2.ini, но он не работает, окно все равно каждый раз запускается рандомно). При этом если запускать клиент сторонним лаунчером (например l2alone), то этот лаунтчер имеет такую фичу - запускать клиент с определенной позицией (вероятно лаунчер передает какие-то флаги клиенту при запуске). Помогите пожалуйста найти ответ на этот вопрос.
Заранее огромное вам спасибо!
 
надоело каждый раз при запуске окон двигать их руками в 21м веке, в разгар ИИ и прочих историй, поэтому решил поинтересоваться у знающих на форуме (те, кто на атомы расщепил клиент) где это можно исполнить, но пока только рекомендации в совсем другую степь (напиши доп. утилю/а зачем? и т.д.)
 
Я хз, есть ли в дефолтном патче ИЛ файл WindowsInfo.ini? На ХФ вроде инфа о положении окон в нем хранится, если я ничего не путаю.
 
Без стороннего по такую муть ты не сделаешь
 
путь пользователей IL - путь страданий

ЛА2- это вцелом путь страданий и самомазахизма) так что ИЛ-бойцы получается самые крутые, правоверные и трушные) круче только ц1щики

ЗЫ: клиент ИЛ каждый раз открывается с одними и теми же размерами, но одинаковым смещением от угла. бесит. и опять гамма слетела к херам от него.. глаза терь выжигает
 
Последнее редактирование:
На ИТ этот файл есть, но он отвечает за внутриигровые окна, а человеку из темы надо чтобы само окно л2 открывалось в нужном месте.
 
Спасибо, в глаза долблюсь. Прочитал первое сообщение не внимательно(
 
Как нет, есть в файле Option.ini
Раздел
[Video]
GamePlayViewportX=1024 тут выставляешь разрешения своего экрана.
GamePlayViewportY=768
 
Это "разрешение экрана", а не расположение окна.
 
ну как там получается через *.ini? теперь понял к чему это ?
 
Вобще, если ТСу надо чисто для себя, то можно не заморачиваться с написанием какой-то проги, а заюзать к примеру для запуска тот же AutoIt - у него функции запуска прог в нужных координатах вроде как имеются, по сути просто юзающие те же CreateProcess и т.п. из WinAPI.
 
Реакции: òbi
Посмотреть как работает тот самый лаунчер нет возможности?

В любом случает вот вариант позиционирования окна клиента (в данном примере по центру). По сути запускает основной процесс 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 (исходы и компил прикрепил)
 

Вложения

  • L2.zip
    12,3 КБ · Просмотры: 12
Последнее редактирование:

а как в таком запуске происходит процесс запоминания изменений окна? допустим после некоторого запуска человек меняет положение левого верхнего края окна и его размер перед закрытием. по коду я так понял она не отслеживает этого и надо дописывать? И я правильно понял, что этот "запускатель" выключается после выполненой задачи центрирования запущенного окна ЛА2?
 
а как в таком запуске происходит процесс запоминания изменений окна?
никак, поскольку и не запоминает. Да и зачем, если задача текущего кода запускать/корректировать окно по центру.
хм, а отслеживать чужое окно скорее всего и не получится, по крайне мере у меня не получилось через SetWindowLong с флагом GWL_WNDPROC. Может как можно повесть слушателя WndProc через ChangeWindowMessageFilter(Ex). Будет еще время и желание, потыкаю. Но пока судя по всему работать с окном, которое мы не создавали из текущего процесса, попросту нельзя.
Все верно, по завершению манипуляций с окном процесс закрывается.
 
Последнее редактирование:
Зачем создавать велосипед когда он уже есть. DxWnd.
 

    òbi

    Баллов: 0
    Из спортивного интереса, не более ;)

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