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

Neo`

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

Я хз, есть ли в дефолтном патче ИЛ файл WindowsInfo.ini? На ХФ вроде инфа о положении окон в нем хранится, если я ничего не путаю.
 
Без стороннего по такую муть ты не сделаешь
 
путь пользователей IL - путь страданий :)

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

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

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

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

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

    òbi

    Баллов: 0
    Из спортивного интереса, не более ;)
никак, поскольку и не запоминает. Да и зачем, если задача текущего кода запускать/корректировать окно по центру.

хм, а отслеживать чужое окно скорее всего и не получится, по крайне мере у меня не получилось через SetWindowLong с флагом GWL_WNDPROC. Может как можно повесть слушателя WndProc через ChangeWindowMessageFilter(Ex). Будет еще время и желание, потыкаю. Но пока судя по всему работать с окном, которое мы не создавали из текущей процесса, попросту нельзя.

Все верно, по завершению манипуляций с окном процесс закрывается.

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