Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.62/13: Рейтинг темы: голосов - 13, средняя оценка - 4.62
0 / 0 / 0
Регистрация: 05.10.2014
Сообщений: 67

Как расположить клиентскую область стороннего окна в определённой позиции экрана

08.11.2014, 19:32. Показов 2873. Ответов 13
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Собственно, задача проста: надо расположить стороннее приложение так, что бы его клиентская область начиналась с позиции Х, Y и была размером Width, Height.

Что пробовалось:
Win32.SetWindowPos - задаёт позицию и размер всего окна, при этом клиентская область урезается согласно настройкам персонализации Виндовс.
класс SystemInformation - так и не нашёл в нём толщин бордюров для разных стилей винды.

Нашёл волшебную функцию AdjustWindowRectEx, которая в связке с SetWindowPos обещает решить проблему, но не получается совладать с её параметрами (непонятно что писать на месте стилей/какие текущие стили брать).

Xотелось бы решить этот вопрос средствами С# (мне почему то кажется, что он всё же должен обладать необходимыми инструментами). На худой конец, если это невозможно без импорта сторонних библиотек, то любым доступным способом.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
08.11.2014, 19:32
Ответы с готовыми решениями:

Вывести системное время в определенной позиции экрана
Здравствуйте! как можно вывести системное время (текущую дату, месяц, день, часы, минуты, секунды и миллисекунды) в окно WinAPI c++ в...

Ввести символ. Вывести его в определённой позиции экрана
Здравствуйте!Помогите пожалуйста с информатикой. Задание 1. Написать 16–ти разрядную ассемблерную программу, которая выполняет...

Как перерисовать всю клиентскую область?
Всем доброго времени суток. Подскажите пожалуйста, как заставить свое окно перерисовываться полностью в момент его неактивности? ...

13
Администратор
Эксперт .NET
 Аватар для tezaurismosis
9670 / 4823 / 762
Регистрация: 17.04.2012
Сообщений: 9,661
Записей в блоге: 14
09.11.2014, 15:44
Andreys5, код достаточно простой, если использовать MoveWindow()
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
 
namespace ConsoleApplication
{
    class Program
    {
        [DllImport("user32.dll")]
        public static extern bool MoveWindow(
            IntPtr hWnd, int x, int y, int nWidth, int nHeight, bool bRepaint);
 
        static void Main(string[] args) {
            Process notepad = Process.GetProcessesByName("notepad")[0];
            MoveWindow(notepad.MainWindowHandle, 500, 500, 100, 100, true);
        }
    }
}
0
0 / 0 / 0
Регистрация: 05.10.2014
Сообщений: 67
09.11.2014, 19:04  [ТС]
tezaurismosis, код действительно простой, но задачи не решает. MoveWindow, равно как и SetWindowPos, перемещает всё окно в нужную позицию и делает его нужного размера. Но.. Клиентская область опять же неопределённого размера.

Что я имею ввиду под клиентской областью: запустим cmd.exe - всё что чёрное - это клиентская область. Т.е. полоса прокрутки, бордюры, заголовок (толщины которых зависят от личных установок/стилей Винды на разных ПК) - сужают нашу клиентскую область.
И если я сделаю MoveWindow(hWnd, 100, 100, 600, 600, true) - то я получу всё окно приложения размером 600*600, но сама клиентская область (та чёрная область в cmd.exe) будет в зависимости от стилей - разная.

Вопрос по прежнему открыт.
0
Администратор
Эксперт .NET
 Аватар для tezaurismosis
9670 / 4823 / 762
Регистрация: 17.04.2012
Сообщений: 9,661
Записей в блоге: 14
09.11.2014, 20:05
Тогда код будет чуть сложнее, но принцип всё же прост
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
 
namespace ConsoleApplication
{
    [StructLayout(LayoutKind.Sequential)]
    public struct Rect
    {
        public int Left   { set; get; }
        public int Top    { set; get; }
        public int Right  { set; get; }
        public int Bottom { set; get; }
 
        public Rect(int left, int top, int right, int bottom) : this() {
            Left = left;
            Top = top;
            Right = right;
            Bottom = bottom;
        }
    }
 
    class Program
    {
        [DllImport("user32.dll")]
        public static extern bool MoveWindow(
            IntPtr hWnd, int x, int y, int nWidth, int nHeight, bool bRepaint);
 
        [DllImport("user32.dll")]
        public static extern bool AdjustWindowRectEx(
            ref Rect lpRect, uint dwStyle, bool bMenu, uint dwExStyle);
 
        [DllImport("user32.dll", SetLastError = true)]
        public static extern uint GetWindowLong(IntPtr hWnd, int nIndex);
 
        [DllImport("user32.dll")]
        public static extern IntPtr GetMenu(IntPtr hWnd);
 
        [DllImport("user32.dll")]
        static extern bool GetWindowRect(IntPtr hwnd, out Rect lpRect);
 
        public const int GWL_STYLE = -16;
        public const int GWL_EXSTYLE = -20;
 
        static void Main(string[] args) {
            Process notepad = Process.GetProcessesByName("notepad")[0];
            Rect newRect = new Rect(300, 100, 500, 200);
            IntPtr wndHandle = notepad.MainWindowHandle;
            // изменяем размеры клиентской области
            // это меняет только прямоугольник,
            // для окна нужно применить отдельно
            AdjustWindowRectEx(ref newRect,
                GetWindowLong(wndHandle, GWL_STYLE),
                GetMenu(wndHandle).ToInt32() == 0 ? false : true,
                GetWindowLong(wndHandle, GWL_EXSTYLE));
 
            Rect oldRect = new Rect();
            // сохраняем предыдущие размеры
            GetWindowRect(wndHandle, out oldRect);
            // меняем размеры
            MoveWindow(wndHandle, oldRect.Left, oldRect.Top,
                newRect.Right - newRect.Left,
                newRect.Bottom - newRect.Top, true);
        }
    }
}
0
0 / 0 / 0
Регистрация: 05.10.2014
Сообщений: 67
09.11.2014, 23:06  [ТС]
Спасибо большое.. Похоже, это уже в нужном направлении... Этот код делает в итоге клиентское окно размером 184*84. Если я правильно понял, оно должно было быть 500*200. Где ошибка?

Ещё вопрос, почему GWL_STYLE и GWL_EXSTYLE принимают именно такие значения?

Добавлено через 17 минут
Подозреваю, что размер прямоугольника должен задаваться как Rect newRect = new Rect(0, 0, 500, 200).
Но даже в этом случае размер клиентского окна 497*197 (как раз, наверное, видим влияние стилей Виндовс).

Так что пока результата нет Но решение явно где то рядом...
0
Администратор
Эксперт .NET
 Аватар для tezaurismosis
9670 / 4823 / 762
Регистрация: 17.04.2012
Сообщений: 9,661
Записей в блоге: 14
10.11.2014, 08:03
Цитата Сообщение от Andreys5 Посмотреть сообщение
Но даже в этом случае размер клиентского окна 497*197
Тогда вообще непонятно, что вам нужно. Писали сначала
Цитата Сообщение от Andreys5 Посмотреть сообщение
надо расположить стороннее приложение так, что бы его клиентская область начиналась с позиции Х, Y и была размером Width, Height.
Я не знаю, про какой ещё вы размер говорите. О назначениях параметров в функциях написано в MSDN. Сначала определитесь с тем, что вам нужно, мне как-то не хочется писать код и ждать, чем закончится ваше гадание.
Короче вся работа впустую.
0
0 / 0 / 0
Регистрация: 05.10.2014
Сообщений: 67
10.11.2014, 12:08  [ТС]
tezaurismosis, не обижайтесь пожалуйста. Я ценю вашу работу... Возможно, имеет место просто недопонимание вопроса...

Да, мне нужно что бы клиентская область начиналась с позиции Х, Y и была размером Width, Height (например 500*200).
Давайте на примере cmd.exe, т.к. там проще объяснять.

В нашем конкретном примере мне надо что бы клиентская область cmd (всё что чёрное) - была размером 500*200 и располагалась в позиции например 100, 100.
MoveWindow(hWnd, 100, 100, 500, 200, true) - уложит всё окно консоли в этот размер - бордюры, шапку, полосы прокрутки и чёрную клиентскую область. Т.е. сама область будет меньше на эти значения. Какая именно у конкретного пользователя она будет - неизвестно. А надо что бы было 500*200, а всё остальное что бы было вокруг этого размера.

Согласно MSDN AdjustWindowRectEx() призвана вернуть нам необходимый размер окна, если ей скормить нужный размер клиентской области и некие стили. Согласно стилям она выяснит ширину бордюров и прочего, прибавит это к нашему прямоугольнику и вернёт новый размер, который и необходимо указать при вызове MoveWindow.

Но, по факту, в приведённом вами коде AdjustWindowRectEx возвращает значение, которое в итоге не даёт нам требуемый размер клиентской области (а требуем мы его явно, указывая 500, 200 - а получили почему то 497 на 197).

Но всё же размер возвращаемого окна увеличен, а это значит, что AdjustWindowRectEx всё же пытается что то делать, но, либо она неправильно работает, либо ей неправильно заданы входные параметры (а именно стили, о которых я спрашивал).

Вот и получается, что вопрос упирается вызов AdjustWindowRectEx() с правильными параметрами.
Надеюсь, теперь я доступно объяснил суть проблемы...
0
Администратор
Эксперт .NET
 Аватар для tezaurismosis
9670 / 4823 / 762
Регистрация: 17.04.2012
Сообщений: 9,661
Записей в блоге: 14
10.11.2014, 12:47
Цитата Сообщение от Andreys5 Посмотреть сообщение
Ещё вопрос, почему GWL_STYLE и GWL_EXSTYLE принимают именно такие значения?
WinAPI написана на Си (большей частью), поэтому то, что на C# можно было бы представить в виде перечислений, на Си представлено как просто список констант. Это число не содержит в себе никакого скрытого смысла и находится как справочное значение (смотрим в MSDN или в заголовочном файле)

Я поменял параметры, поступающие в метод AdjustWindowRectEx (изменил newRect)
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
 
namespace ConsoleApplication
{
    [StructLayout(LayoutKind.Sequential)]
    public struct Rect
    {
        public int Left   { set; get; }
        public int Top    { set; get; }
        public int Right  { set; get; }
        public int Bottom { set; get; }
 
        public Rect(int left, int top, int right, int bottom) : this() {
            Left = left;
            Top = top;
            Right = right;
            Bottom = bottom;
        }
    }
 
    class Program
    {
        [DllImport("user32.dll")]
        public static extern bool MoveWindow(
            IntPtr hWnd, int x, int y, int nWidth, int nHeight, bool bRepaint);
 
        [DllImport("user32.dll")]
        public static extern bool AdjustWindowRectEx(
            ref Rect lpRect, uint dwStyle, bool bMenu, uint dwExStyle);
 
        [DllImport("user32.dll", SetLastError = true)]
        public static extern uint GetWindowLong(IntPtr hWnd, int nIndex);
 
        [DllImport("user32.dll")]
        public static extern IntPtr GetMenu(IntPtr hWnd);
 
        [DllImport("user32.dll")]
        public static extern bool GetWindowRect(IntPtr hwnd, out Rect lpRect);
 
        [DllImport("user32.dll")]
        public static extern bool GetClientRect(IntPtr hwnd, out Rect lpRect);
 
        public const int GWL_STYLE = -16;
        public const int GWL_EXSTYLE = -20;
 
        static void Main(string[] args) {
            Process notepad = Process.GetProcessesByName("notepad")[0];
            // если нужно окно с клиентской областью 500 x 100
            // передавайте 0, 0, 500, 100
            Rect newRect = new Rect(0, 0, 500, 100);
            IntPtr wndHandle = notepad.MainWindowHandle;
 
            AdjustWindowRectEx(ref newRect,
                GetWindowLong(wndHandle, GWL_STYLE),
                GetMenu(wndHandle).ToInt32() == 0 ? false : true,
                GetWindowLong(wndHandle, GWL_EXSTYLE));
 
            Rect oldRect = new Rect();
            // сохраняем предыдущие размеры
            GetWindowRect(wndHandle, out oldRect);
            // oldRect = B 664, L 154, R 854, T 123
            // меняем размеры
            MoveWindow(wndHandle, oldRect.Left, oldRect.Top,
                newRect.Right - newRect.Left,
                newRect.Bottom - newRect.Top, true);
 
            // см. в отладчике
            Rect clientRect = new Rect();
            GetClientRect(wndHandle, out clientRect);
            // clientRect = B 100, L 0, R 500, T 0
            Rect windowRect = new Rect();
            GetWindowRect(wndHandle, out windowRect);
            // windowRect = B 281, L 154, R 670, T 123
            // проверил размеры в Paint'е - 516 х 158
            // если посчитать вручную: 670 - 154 = 516 х 281 - 123 = 158
        }
    }
}
Получили окно - клиентская область - 500 х 100, размеры самого окна - 516 х 158, как видите, увеличенные за счёт рамок.
Это было нужно?

Добавлено через 6 минут
Цитата Сообщение от Andreys5 Посмотреть сообщение
располагалась в позиции например 100, 100
Тогда нужно отдельно передать позицию в MoveWindow, например так
C#
1
2
3
MoveWindow(wndHandle, 100, 100,
    newRect.Right - newRect.Left,
    newRect.Bottom - newRect.Top, true);
Если результат вас устраивает, я могу переписать весь код в один метод, чтобы было удобнее использовать.
0
0 / 0 / 0
Регистрация: 05.10.2014
Сообщений: 67
10.11.2014, 14:01  [ТС]
Похоже, я в той ситуации, когда не знаешь что сказать, проще показать..

Копировал код один к одному, лишь заменил GetProcessesByName("notepad") на GetProcessesByName("cmd"), запустил, получил это:



Что из этого считать необходимым мне 500*100 я не знаю, т.к. тут его нигде нет(
В чём может быть проблема?

Добавлено через 6 минут
рассматривая картинку я подметил, что 505 и 101 больше необходимых 500 и 100 на 1%
Вероятно совпадение... Или...
0
Администратор
Эксперт .NET
 Аватар для tezaurismosis
9670 / 4823 / 762
Регистрация: 17.04.2012
Сообщений: 9,661
Записей в блоге: 14
10.11.2014, 14:05
Цитата Сообщение от Andreys5 Посмотреть сообщение
В чём может быть проблема?
Без понятия. Измерьте также какое-нибудь другое приложение, не консоль. Предполагаю, что рамки залазят на клиентскую область
0
0 / 0 / 0
Регистрация: 05.10.2014
Сообщений: 67
10.11.2014, 14:05  [ТС]
Я согласен уже и на то что бы хотя бы хоть какие то размеры соответствовали заданным, хотя, в идеале, мне бы размер чёрного прямоугольника без полей прокрутки...
0
0 / 0 / 0
Регистрация: 05.10.2014
Сообщений: 67
10.11.2014, 14:13  [ТС]
Проверил на Блокноте - отрабатывает чётко 500*100 (но это с учётом полос прокрутки). Спасибо огромное.

Консоль проверю на разных компах с разными настройками Виндовс.
Как всё же избавиться от учёта толщин полос прокрутки?
0
Администратор
Эксперт .NET
 Аватар для tezaurismosis
9670 / 4823 / 762
Регистрация: 17.04.2012
Сообщений: 9,661
Записей в блоге: 14
10.11.2014, 14:25
Цитата Сообщение от Andreys5 Посмотреть сообщение
Как всё же избавиться от учёта толщин полос прокрутки?
В коде добавить её ширину. Их можно получить без WinAPI (http://stackoverflow.com/a/856919/3816620)
(код переработан)
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
 
namespace ConsoleApplication
{
    public class User32
    {
        [StructLayout(LayoutKind.Sequential)]
        public struct Rect
        {
            public int Left { set; get; }
            public int Top { set; get; }
            public int Right { set; get; }
            public int Bottom { set; get; }
 
            public Rect(int left, int top, int right, int bottom)
                : this() {
                Left = left;
                Top = top;
                Right = right;
                Bottom = bottom;
            }
        }
 
        [DllImport("user32.dll")]
        public static extern bool MoveWindow(
            IntPtr hWnd, int x, int y, int nWidth, int nHeight, bool bRepaint);
 
        [DllImport("user32.dll")]
        public static extern bool AdjustWindowRectEx(
            ref Rect lpRect, uint dwStyle, bool bMenu, uint dwExStyle);
 
        [DllImport("user32.dll", SetLastError = true)]
        public static extern uint GetWindowLong(IntPtr hWnd, int nIndex);
 
        [DllImport("user32.dll")]
        public static extern IntPtr GetMenu(IntPtr hWnd);
 
        [DllImport("user32.dll")]
        public static extern bool GetWindowRect(IntPtr hwnd, out Rect lpRect);
 
        [DllImport("user32.dll")]
        public static extern bool GetClientRect(IntPtr hwnd, out Rect lpRect);
 
        public const int GWL_STYLE = -16;
        public const int GWL_EXSTYLE = -20;
    }
 
    class Program
    {
        /// <summary>
        /// Располагает окно и изменяет его размеры так, чтобы клиентская
        /// область окна и верхний левый его угол соответствовали параметрам.
        /// </summary>
        /// <param name="wndHandle">Дексриптор окна</param>
        /// <param name="x">Расстояние в пискелях от левого края 
        /// экрана до левого края окна</param>
        /// <param name="y">Расстояние в пискелях от верхнего края
        /// экрана до верхнего края окна</param>
        /// <param name="width">Ширина клиентской области окна</param>
        /// <param name="height">Высота клиентской области окна</param>
        /// <param name="substractScrollBars">Увелчить клиентскую область 
        /// на размер полос прокрутки</param>
        /// <remarks>В связи с наличие у окна рамок, размер окна 
        /// будет больше размера его клиентской области</remarks>
        public static void SetClientRect
            (IntPtr wndHandle, int x, int y,
            int width, int height, bool substractScrollBars)
        {
            if (substractScrollBars) {
                width += SystemInformation.VerticalScrollBarWidth;
                height += SystemInformation.HorizontalScrollBarHeight;
            }
            var newRect = new User32.Rect(0, 0, width, height);
            User32.AdjustWindowRectEx(ref newRect,
                User32.GetWindowLong(wndHandle, User32.GWL_STYLE),
                User32.GetMenu(wndHandle).ToInt32() == 0 ? false : true,
                User32.GetWindowLong(wndHandle, User32.GWL_EXSTYLE));
            User32.MoveWindow(wndHandle, x, y,
                newRect.Right - newRect.Left,
                newRect.Bottom - newRect.Top, true);
 
        }
 
        static void Main(string[] args) {
            Process notepad = Process.GetProcessesByName("notepad")[0];
            IntPtr wndHandle = notepad.MainWindowHandle;
 
            SetClientRect(wndHandle, 20, 20, 150, 400, true);
        }
    }
}
0
0 / 0 / 0
Регистрация: 05.10.2014
Сообщений: 67
10.11.2014, 15:27  [ТС]
tezaurismosis, спасибо большое.
Идея ясна, дальше буду допиливать напильником)
(а именно: сейчас код учитывает только правую полосу прокрутки и не учитывает нижнюю, располагает в нужной позиции не клиентскую область а само окно(клиентская получается ниже на некую высоту), странные координаты для перемещаемого консольного приложения).
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
10.11.2014, 15:27
Помогаю со студенческими работами здесь

Расположить график в заданной позиции графического интерфейса (окна)
Здравствуйте, возникла проблема со вставкой графика в определенное место в созданный графический интерфейс, если более точнее, то хотел...

Как сделать клиентскую область формы во весь экран
нужна помощь вот в каком деле ShowWindow(Result, SC_MAXIMIZE); не катит нуна сделать форму во весь экран т.е. что бы не было видно вот...

Растянуть контрол на всю клиентскую область
добрый вечер! для С# мне нужна альтернатива свойству Align из Delphi со значением AllClient - то есть чтобы компонент занял всю...

Скопировать часть строки с определенной позиции и определенной длины в другую строку
Ввести с клавиатуры строку. Скопировать часть строки с определенной позиции и определенной длины в другую строку. Номер позиции и...

Строка: Скопировать часть строки с определенной позиции и определенной длины в другую строку
Скопировать часть строки с определенной позиции и определенной длины в другую строку. Например: дана строка &quot;Функция для работы со...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru