С Новым годом! Форум программистов, компьютерный форум, киберфорум
Visual Basic
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.85/20: Рейтинг темы: голосов - 20, средняя оценка - 4.85
958 / 570 / 40
Регистрация: 10.09.2021
Сообщений: 2,382
1

Как создать на VB6 уникодный InputBox? Чтобы при вводе в InputBox можно было получать китайские иероглифы и так далее

15.11.2023, 22:50. Показов 4029. Ответов 51

Author24 — интернет-сервис помощи студентам
Как создать на VB6 уникодный InputBox? Чтобы при вводе в InputBox можно было получать китайские иероглифы и так далее. Текстовое поле InputBox'а, что самое интересное и так позволяет вводить китайщину, но вот на выходе функции мы получаем уже знаки вопросов...

Добавлено через 54 минуты
Хотите чудо? InputBox создаётся с ANSI-окнами, и с ANSI текстовым полем, без стилизации окна манифестом...
Со стилизацией манифестом уже создаётся Unicode окна и уникодное текстовое поле ввода... Это очень странно и меня очень шокировало...

Добавлено через 15 минут
Таким образом, уникодный InputBox будет работать только если стилизовать программу, применить стили красивостей окон. В противном случае пришлось бы уничтожать старый Edit через DestroyWindow и поверх создавать новое текстовое поле через CreateWindowExW... Чтобы работало и без стилей...
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
15.11.2023, 22:50
Ответы с готовыми решениями:

Можно ли настроить Inputbox, чтобы не блокировалась книга и можно было изменять данные в ячейках?
Всем привет! Подскажите, можно ли настроить Inputbox так, чтобы не блокировалась книга и можно...

как сделать чтоб при вводе в inputbox вводились толька символы 0.123456789
Вопрос такой как сделать чтоб при вводе в inputbox вводились толька символы 0.123456789 чтоб...

Обработать событие OnKeyPress при вводе целого числа в Edit так, чтобы можно было вставить только один знак минус
помогите решить) Обработать событие OnKeyPress при вводе целого числа в Edit так, чтобы можно было...

Как сделать так, чтобы при вводе в консоле не было перехода на новую строку?
Допустим у меня есть: #include<iostream> using namespace std; int main() { int a; ...

Можно ли так сделать так,чтобы предыдущего окно закрывалось при нажатие кнопки далее
from tkinter import * from tkinter import messagebox from tkinter import filedialog def...

51
958 / 570 / 40
Регистрация: 10.09.2021
Сообщений: 2,382
15.11.2023, 23:41  [ТС] 2
Ну всё, за пару часов написал этот модуль.

Visual Basic
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
Option Explicit
'////////////////////////////////////////////
'// Модуль создания уникодного InputBox'а  //
'// Copyright (c) 15.11.2023 by HackerVlad //
'// e-mail: vladislavpeshkov@yandex.ru     //
'// Версия 1.0                             //
'////////////////////////////////////////////
 
Private Declare Function SetWinEventHook Lib "user32" (ByVal eventMin As Long, ByVal eventMax As Long, ByVal hmodWinEventProc As Long, ByVal pfnWinEventProc As Long, ByVal idProcess As Long, ByVal idThread As Long, ByVal dwFlags As Long) As Long
Private Declare Function UnhookWinEvent Lib "user32" (ByVal hWinEventHook As Long) As Long
Private Declare Function GetClassName Lib "user32" Alias "GetClassNameW" (ByVal hwnd As Long, ByVal lpClassName As Long, ByVal nMaxCount As Long) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageW" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function SetWindowSubclass Lib "comctl32" Alias "#410" (ByVal hwnd As Long, ByVal pfnSubclass As Long, ByVal uIdSubclass As Long, Optional ByVal dwRefData As Long) As Long
Private Declare Function RemoveWindowSubclass Lib "comctl32" Alias "#412" (ByVal hwnd As Long, ByVal pfnSubclass As Long, ByVal uIdSubclass As Long) As Long
Private Declare Function DefSubclassProc Lib "comctl32" Alias "#413" (ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function DefWindowProcW Lib "user32" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWndParent As Long, ByVal hWndChildAfter As Long, ByVal lpClassName As String, ByVal lpWindowName As String) As Long
 
Private Const EVENT_OBJECT_SHOW As Long = &H8002&
Private Const WM_COMMAND = &H111
Private Const IDOK = 1
Private Const WM_GETTEXT As Long = &HD
Private Const WM_GETTEXTLENGTH As Long = &HE
Private Const WM_SETTEXT = &HC
Private Const EM_SETSEL = &HB1
 
Dim hEvent As Long
Dim HandleDialogWindow As Long
Dim HandleEdit As Long
Dim Subclassed As Long
Dim InputText As String
Dim TitleCaption As String
Dim DialogPrompt As String
Dim TextDefault As String
 
Public Function InputBoxW(ByVal strPrompt As String, Optional ByVal strTitle As String, Optional ByVal strDefault As String) As String
    InputText = vbNullString
    HandleDialogWindow = 0
    Subclassed = 0
    HandleEdit = 0
    hEvent = 0
    
    ' Устанавливаем хук на создание окон в системе
    hEvent = SetWinEventHook(EVENT_OBJECT_SHOW, EVENT_OBJECT_SHOW, 0, AddressOf WinEventProc, 0, App.ThreadID, 0)
    
    DialogPrompt = strPrompt
    TitleCaption = strTitle
    TextDefault = strDefault
    
    InputBox strPrompt, "" ' Вызвать классический InputBox
    
    RemoveWindowSubclass Subclassed, AddressOf WndProc, 0 ' Снять субклассирование
    If hEvent > 0 Then UnhookWinEvent hEvent
    
    InputBoxW = InputText
End Function
 
' Функция вызывается при создании окна
Private Sub WinEventProc(ByVal hWinEventHook As Long, ByVal dwEvent As Long, ByVal hwnd As Long, ByVal idObject As Long, ByVal idChild As Long, ByVal dwEventThread As Long, ByVal dwmsEventTime As Long)
    Dim cls As String
    Dim sLn As Long
    Dim hwndStatic As Long
    
    cls = Space(256)
    
    ' Получаем имя класса окна
    sLn = GetClassName(hwnd, StrPtr(cls), Len(cls))
    
    If sLn Then
        cls = Left(cls, sLn)
        
        If StrComp(cls, "Edit", vbTextCompare) = 0 Then
            HandleEdit = hwnd ' Запомнить hwnd текстового поля
        End If
        
        If cls = "#32770" Then ' Если класс этого окна это диалоговое окно
            HandleDialogWindow = hwnd ' Запомнить hwnd диалогового окна
            hwndStatic = FindWindowEx(hwnd, ByVal 0&, "Static", vbNullString) ' Найти Static
            If TitleCaption = "" Then TitleCaption = App.Title
            
            ' Установить заголовок окна с поддержкой уникода (SendMessage не работает в этом случае)
            DefWindowProcW hwnd, WM_SETTEXT, 0, StrPtr(TitleCaption)
            
            ' Установить заголовок окна с поддержкой уникода (а вот здесь SendMessage уже работает почему-то)
            SendMessage hwndStatic, WM_SETTEXT, 0, StrPtr(DialogPrompt)
            
            If Len(TextDefault) > 0 Then
                SendMessage HandleEdit, WM_SETTEXT, 0, StrPtr(TextDefault)
                SendMessage HandleEdit, EM_SETSEL, 0, -1
            End If
            
            If HandleEdit > 0 And HandleDialogWindow > 0 Then
                ' Снять хук, если мы получили оба значения и HandleDialogWindow и HandleEdit
                If hEvent > 0 Then ' Только единожды
                    UnhookWinEvent hEvent
                    hEvent = 0
                End If
            End If
            
            If Subclassed = 0 Then
                Subclassed = SetWindowSubclass(HandleDialogWindow, AddressOf WndProc, 0&)
            End If
        End If
    End If
End Sub
 
Private Function WndProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long, ByVal uIdSubclass As Long, ByVal dwRefData As Long) As Long
    Dim bProcessed As Boolean
    Dim TextLen As Long
    
    Select Case uMsg
        Case WM_COMMAND
            If wParam = IDOK Then ' Событие которое обрабатывается при нажатии ОК
                InputText = Space$(256)
                TextLen = SendMessage(HandleEdit, WM_GETTEXTLENGTH, 0, 0)
                SendMessage HandleEdit, WM_GETTEXT, TextLen + 1, StrPtr(InputText)
                InputText = Left$(InputText, TextLen)
            End If
    End Select
    
    If Not bProcessed Then
        WndProc = DefSubclassProc(hwnd, uMsg, wParam, lParam)
    End If
End Function
В форме достаточно написать вместо InpuBox просто InpuBoxW:

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Option Explicit
Private Declare Function DefWindowProcW Lib "user32" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Const WM_SETTEXT = &HC
 
Private Sub Command1_Click()
    Dim str As String
    
    str = InputBoxW("Китайский язык приветствуется. " & vbNewLine & "Введите китайщину (например " & ChrW(&H88E7) & "):", "Дружба народов " & ChrW(&H88E7), "Это китайский символ - " & ChrW(&H88E7))
    
    If Len(str) > 0 Then
        DefWindowProcW Me.hwnd, WM_SETTEXT, 0, ByVal StrPtr(Chr(34) & str & Chr(34))
    Else
        Me.Caption = "Canceled."
    End If
End Sub
 
Private Sub Form_Initialize()
    InitCommonControlsXP
End Sub
Но обязательно нужен файл манифеста для стилизации окна чтобы были красивости. Я прилагаю архив, там манифест уже вшит в EXE в ресурсах там. Теперь всё работает как надо)))
Миниатюры
Как создать на VB6 уникодный InputBox? Чтобы при вводе в InputBox можно было получать китайские иероглифы и так далее  
Вложения
Тип файла: zip Уникодный InputBox.zip (10.1 Кб, 6 просмотров)
1
958 / 570 / 40
Регистрация: 10.09.2021
Сообщений: 2,382
16.11.2023, 03:06  [ТС] 3
У этого модуля, версии 1.0, оказался один недостаток: при классическом стиле Windows заглючил заголовок диалогового окна... Сначала в фокусе он появляется, без отображения китайщины, с вопросительным знаком... а потом когда фокус окна теряется то почему-то китайский иероглиф всё равно вылазит. Ещё раз подчёркиваю, только в классическом стиле Windows.
Миниатюры
Как создать на VB6 уникодный InputBox? Чтобы при вводе в InputBox можно было получать китайские иероглифы и так далее  
1
958 / 570 / 40
Регистрация: 10.09.2021
Сообщений: 2,382
16.11.2023, 14:36  [ТС] 4
Но зато я написал сейчас новый модуль, версии 1.1 уже, где этот глюк я исправил и теперь даже в классическом стиле Windows китайщина правильно отображается в заголовке.

Visual Basic
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
Option Explicit
'////////////////////////////////////////////
'// Модуль создания уникодного InputBox'а  //
'// Copyright (c) 16.11.2023 by HackerVlad //
'// e-mail: vladislavpeshkov@yandex.ru     //
'// Версия 1.1                             //
'////////////////////////////////////////////
 
Private Declare Function SetWinEventHook Lib "user32" (ByVal eventMin As Long, ByVal eventMax As Long, ByVal hmodWinEventProc As Long, ByVal pfnWinEventProc As Long, ByVal idProcess As Long, ByVal idThread As Long, ByVal dwFlags As Long) As Long
Private Declare Function UnhookWinEvent Lib "user32" (ByVal hWinEventHook As Long) As Long
Private Declare Function GetClassName Lib "user32" Alias "GetClassNameW" (ByVal hwnd As Long, ByVal lpClassName As Long, ByVal nMaxCount As Long) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageW" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function SetWindowText Lib "user32" Alias "SetWindowTextW" (ByVal hwnd As Long, ByVal lpString As Long) As Long
Private Declare Function SetWindowSubclass Lib "comctl32" Alias "#410" (ByVal hwnd As Long, ByVal pfnSubclass As Long, ByVal uIdSubclass As Long, Optional ByVal dwRefData As Long) As Long
Private Declare Function RemoveWindowSubclass Lib "comctl32" Alias "#412" (ByVal hwnd As Long, ByVal pfnSubclass As Long, ByVal uIdSubclass As Long) As Long
Private Declare Function DefSubclassProc Lib "comctl32" Alias "#413" (ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
 
Private Const EVENT_OBJECT_CREATE As Long = &H8000&
Private Const WM_COMMAND = &H111
Private Const IDOK = 1
Private Const WM_GETTEXT As Long = &HD
Private Const WM_GETTEXTLENGTH As Long = &HE
Private Const WM_SETTEXT = &HC
Private Const EM_SETSEL = &HB1
Private Const WM_SHOWWINDOW As Long = &H18
 
Dim hEvent As Long
Dim HandleDialogWindow As Long
Dim HandleStatic As Long
Dim HandleEdit As Long
Dim Subclassed As Long
Dim InputText As String
Dim TitleCaption As String
Dim DialogPrompt As String
Dim TextDefault As String
 
Public Function InputBoxW(ByVal strPrompt As String, Optional ByVal strTitle As String, Optional ByVal strDefault As String) As String
    InputText = vbNullString
    HandleDialogWindow = 0
    HandleStatic = 0
    Subclassed = 0
    HandleEdit = 0
    hEvent = 0
    
    DialogPrompt = strPrompt
    TitleCaption = strTitle
    TextDefault = strDefault
    
    hEvent = SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_CREATE, 0, AddressOf WinEventProc, 0, App.ThreadID, 0) ' Устанавливаем хук на создание окон в системе
    InputBox strPrompt, vbNullString ' Вызвать классический InputBox
    
    RemoveWindowSubclass Subclassed, AddressOf WndProc, 0 ' Снять субклассирование
    If hEvent > 0 Then UnhookWinEvent hEvent
    
    InputBoxW = InputText
End Function
 
' Функция вызывается при создании окна
Private Sub WinEventProc(ByVal hWinEventHook As Long, ByVal dwEvent As Long, ByVal hwnd As Long, ByVal idObject As Long, ByVal idChild As Long, ByVal dwEventThread As Long, ByVal dwmsEventTime As Long)
    Dim cls As String
    Dim sLn As Long
    
    cls = Space(256)
    
    ' Получаем имя класса окна
    sLn = GetClassName(hwnd, StrPtr(cls), Len(cls))
    
    If sLn Then
        cls = Left(cls, sLn)
        
        If HandleDialogWindow = 0 Then
            If cls = "#32770" Then ' Если класс это диалоговое окно
                HandleDialogWindow = hwnd ' Запомнить hwnd диалогового окна
                
                If Subclassed = 0 Then
                    Subclassed = SetWindowSubclass(HandleDialogWindow, AddressOf WndProc, 0&)
                End If
            End If
        End If
        
        If HandleStatic = 0 Then
            If StrComp(cls, "Static", vbTextCompare) = 0 Then
                HandleStatic = hwnd
            End If
        End If
        
        If HandleEdit = 0 Then
            If StrComp(cls, "Edit", vbTextCompare) = 0 Then
                HandleEdit = hwnd ' Запомнить hwnd текстового поля
            End If
        End If
        
        If HandleDialogWindow > 0 And HandleStatic > 0 And HandleEdit > 0 Then
            If hEvent > 0 Then ' Только единожды
                UnhookWinEvent hEvent ' Снять хук
                hEvent = 0
            End If
        End If
    End If
End Sub
 
Private Function WndProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long, ByVal uIdSubclass As Long, ByVal dwRefData As Long) As Long
    Dim bProcessed As Boolean
    Dim TextLen As Long
    
    Select Case uMsg
        Case WM_SHOWWINDOW
            If Len(TitleCaption) = 0 Then TitleCaption = App.Title
            SetWindowText HandleDialogWindow, StrPtr(TitleCaption)
            
            SendMessage HandleStatic, WM_SETTEXT, 0, StrPtr(DialogPrompt)
            
            If Len(TextDefault) > 0 Then
                SendMessage HandleEdit, WM_SETTEXT, 0, StrPtr(TextDefault) ' Установить текст по умолчанию в текстовом поле
                SendMessage HandleEdit, EM_SETSEL, 0, -1 ' Выделить всё в текстовом поле
            End If
        
        Case WM_COMMAND
            If wParam = IDOK Then ' Событие которое обрабатывается при нажатии ОК
                InputText = Space$(256)
                TextLen = SendMessage(HandleEdit, WM_GETTEXTLENGTH, 0, 0)
                SendMessage HandleEdit, WM_GETTEXT, TextLen + 1, StrPtr(InputText)
                InputText = Left$(InputText, TextLen)
            End If
    End Select
    
    If Not bProcessed Then
        WndProc = DefSubclassProc(hwnd, uMsg, wParam, lParam)
    End If
End Function
Миниатюры
Как создать на VB6 уникодный InputBox? Чтобы при вводе в InputBox можно было получать китайские иероглифы и так далее  
Вложения
Тип файла: zip Уникодный InputBox 1.1.zip (10.4 Кб, 3 просмотров)
2
958 / 570 / 40
Регистрация: 10.09.2021
Сообщений: 2,382
16.11.2023, 14:40  [ТС] 5
Вообще с установкой заголовка окна с уникодом в винде есть глюки конечно, SetWindowTextW не всегда и не везде работает, а только при определённых событиях почему-то. Иногда приходится использовать DefWindowProcW но и это тоже не всгда срабатывает. Иногда бывают глюки что в заголовке знак вопроса, а снизу в панеле задач правильная китайщина написана... Это уже разработчики Майкрософт виноваты в этом...
0
958 / 570 / 40
Регистрация: 10.09.2021
Сообщений: 2,382
17.11.2023, 07:10  [ТС] 6
The Trick натолкнул меня на мысль, сказав, что есть функция TaskDialogIndirect. Я начал гуглить, и увидел, что эта замечательная функция позволяет создавать диалоги какие захочешь с новым стилем Vista +

Добавлено через 11 минут
В результате своих поисков я нашёл примеры использования этой функции здесь: https://www.vbforums.com/showthread.php?777021
0
958 / 570 / 40
Регистрация: 10.09.2021
Сообщений: 2,382
17.11.2023, 07:17  [ТС] 7
Иностранцы написали очень хорошо, правда у них огромный класс в котором почти 5 тысяч строк кода... А это не совсем удобно. Жаль, на киберфоруме ничего такого нет.

Итак, немного поколдовав и переделав слегка уже готовый пример я быстро получил диалоговое окно InputBox которое очень красивое и хорошее. Прям мечта, а не диалоговое окно)))

Вот что у меня вышло:

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
With TaskDialog1
    .Init
    .MainInstruction = "Введите имя новой папки:"
    .Content = "E:\Коллекция классов и модулей\2023\Диалог выбора папки 2.5\"
    .Flags = TDF_INPUT_BOX
    .CommonButtons = TDCBF_OK_BUTTON Or TDCBF_CANCEL_BUTTON
    .IconMain = TDN_TIMER
    .Title = "Создание папки"
    .ParenthWnd = Me.hWnd
    .ShowDialog
    
    
    Label5.Caption = .ResultInput
    If .ResultMain = TD_OK Then
        Label1.Caption = "Yes Yes Yes!"
    Else
        Label1.Caption = "Cancelled."
    End If
End With
Вот это просто супер диалоговое окно конечно. Супер InputBox, но работает только начиная с Windows Vista. Но как всегда есть ещё одно но... Но без манифеста тоже не работает... А это тоже огромный минус...

Минусы:

1. Работает только начиная с висты
2. Без манифеста не работает, не находит даже функцию TaskDialogIndirect в comctl32.dll...

Плюсы:

1. Очень красиво и современно
2. Поддерживает юникод
Миниатюры
Как создать на VB6 уникодный InputBox? Чтобы при вводе в InputBox можно было получать китайские иероглифы и так далее  
0
958 / 570 / 40
Регистрация: 10.09.2021
Сообщений: 2,382
17.11.2023, 07:40  [ТС] 8
Я вот сейчас начал думать по поводу этих диалоговых окон и понял: если разработчики заверяют что их код работает и в VBA так же, значит есть способ заставить VBA поддерживать стили манифеста каким-то образом.

Добавлено через 4 минуты
У них кстати совсем нидавно, 8 октября, вышло обновления, как я понял, чтобы поддерживало ещё и VBA полностью, вот что там у них написано:

"Project Update - 08 Oct 2023
Updating this post to Version 1.3 Universal. The features are the same with some bug fixes, but this version universally supports: VB6, VBA6, VBA7 32bit, VBA7 64bit, twinBASIC 32bit, and twinBASIC 64bit..
IMPORTANT: For compatibility, this version no longer uses self-subclassing, and like earlier versions, once again requires mTDHelper.bas in all projects. (mTDSample.bas is still only for the demo form)." А значит поддерживает все версии VBA ихний код. Только интересно как они заставляют VBA поддерживать comctl32.dll версии 6.0 без манифеста, мне лично непонятно...

Добавлено через 1 минуту
Но сам факт: VBA поддерживает. А как я уже без понятия. Для меня даже непонятно как вызвать API функцию comctl32.dll версии 6.0 без манифеста.

Добавлено через 4 минуты
Видимо существует какой-то способ "надевать красивости" на окна без манифеста. Точно так же, как если вызвать диалог выбора папки... То там уже окно стилизовано... Значит каким-то чудом, без манифеста, применяются стили и кнопки становятся красивыми, каким-то чудом интерфейс уже идёт версии 6 из comctl32.dll... Я не знаю как, каким образом и при помощи какого механизма это происходит, но наталкивает на мысль, что это возможно каким-то чудесным образом вообще...
0
958 / 570 / 40
Регистрация: 10.09.2021
Сообщений: 2,382
17.11.2023, 15:26  [ТС] 9
Цитата Сообщение от HackerVlad Посмотреть сообщение
SetWindowTextW не всегда и не везде работает
Я только сейчас понял, что я устанавливаю уникодное имя АНСИшному окну... Поэтому SetWindowTextW и не работает наверное должным образом... Это хорошо что есть ещё хак через DefWindowProcW чтобы установить уникодное имя ANSIшному окну
0
972 / 633 / 75
Регистрация: 08.02.2017
Сообщений: 2,480
Записей в блоге: 1
17.11.2023, 16:17 10
Цитата Сообщение от HackerVlad Посмотреть сообщение
Я только сейчас понял, что я устанавливаю уникодное имя АНСИшному окну... Поэтому SetWindowTextW
Я конечно не в теме, про что конкретно речь, но просто интересно, что в таком случае нельзя, использовать SetWindowTextA?
1
958 / 570 / 40
Регистрация: 10.09.2021
Сообщений: 2,382
17.11.2023, 16:47  [ТС] 11
Цитата Сообщение от testuser2 Посмотреть сообщение
что в таком случае нельзя, использовать SetWindowTextA?
Можно конечно, но только для ANSI'шного имени. Для уникодного имени не получится с китайщиной.

Добавлено через 2 минуты
testuser2, ты кстати попробовал в VBA, то что я тебя просил?
0
972 / 633 / 75
Регистрация: 08.02.2017
Сообщений: 2,480
Записей в блоге: 1
17.11.2023, 18:39 12
HackerVlad, я переделывал твои диалоги, которы v2.0 и они прекрасно работают под vba. Но я не вижу смысла проверять дальше, то что написано на win-api, будет также точно работать под vba, если используются манифесты, то не будет, поскольку vba не поддерживает манифесты. Вообще в принципе я одобряю такие вещи. Вот я допустим, скачал Vba-компилер и сразу вижу в нем огромный недостаток - неудобный файловый диалог. У тебя удосно сделано, то что открываешь диалог и он автоматически проматывается до папки с программой. Я так понимаю там также можно задать папку, на которую будет автоматичеки проматываться дерево?
1
958 / 570 / 40
Регистрация: 10.09.2021
Сообщений: 2,382
17.11.2023, 18:50  [ТС] 13
testuser2, я тебя просил нажать кнопку Создать папку и попробовать ввести китайские иероглифы, в версии 2.5 должно работать и без манифеста, так как сам по себе диалог выбора папки стилизует окно, я говорил уже об этом

Добавлено через 7 минут
Итак, вернёмся к теме диалогов. Уважаемый The Trick советовал использовать функцию DialogBoxIndirectParam для создания своего InputBox. Я искал в интернете примеры использования функции DialogBoxIndirectParam. Оказалось очень сложно хоть что-то найти по этой функции. Прям очень сложно, в интернете почти ничего нет. И в яндексе искал и в гугле и на vbforums искал - ничего нет. Единственное что смог найти на гитхабе это один единсвенный модуль, для VBA, с использованием этой функции где создаётся диалог прогресс бара. Вот здесь: https://gist.github.com/jbuona... ee489f3441

Немного чуть-чуть переделав код, получилось это так же использовать и для VB6:

Visual Basic
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
Option Explicit
 
'-----------------------------------------------------------------------
' Win32 API Declarations
'-----------------------------------------------------------------------
 
Private Type POINTAPI
    x As Long
    y As Long
End Type
 
Private Type MSG
    hWnd As Long
    message As Long
    wParam As Long
    lParam As Long
    time As Long
    pt As POINTAPI
End Type
 
Private Type DLGTEMPLATE
    style As Long
    dwExtendedStyle As Long
    cdit As Integer
    x As Integer
    y As Integer
    cx As Integer
    cy As Integer
End Type
 
Private Type DLGITEMTEMPLATE
    style As Long
    dwExtendedStyle As Long
    x As Integer
    y As Integer
    cx As Integer
    cy As Integer
    id As Integer
End Type
 
Private Type tagINITCOMMONCONTROLSEX
    dwSize As Long
    dwICC As Long
End Type
 
' Window Messages
Private Const WM_INITDIALOG = &H110
Private Const WM_COMMAND = &H111
Private Const WM_CLOSE = &H10
Private Const WM_USER = &H400
 
' Window Styles
Private Const WS_POPUP = &H80000000
Private Const WS_CHILD = &H40000000
Private Const WS_VISIBLE = &H10000000
Private Const WS_CAPTION = &HC00000
Private Const WS_SYSMENU = &H80000
Private Const WS_BORDER = &H800000
 
' Dialog Styles
Private Const DS_CENTER As Long = &H800&
Private Const DS_SETFONT As Long = &H40
Private Const DS_MODALFRAME = &H80
 
' Dialog Box Command IDs
Private Const IDOK = 1
Private Const IDCANCEL = 2
 
' Button Styles
Private Const BS_DEFPUSHBUTTON = &H1&
 
' Init Common Controls Flags
Private Const ICC_PROGRESS_CLASS = &H20
 
' Progress Bar Window Class
Private Const PROGRESS_CLASS As String = "msctls_progress32"
 
' Progress Bar Messages
Private Const PBM_SETPOS = WM_USER + 2
Private Const PBM_DELTAPOS = WM_USER + 3
Private Const PBM_SETSTEP = WM_USER + 4
Private Const PBM_STEPIT = WM_USER + 5
Private Const PBM_SETRANGE32 = WM_USER + 6
Private Const PBM_SETMARQUEE = WM_USER + 10
Private Const PBM_SETSTATE = WM_USER + 16
 
' Progress Bar Styles
Private Const PBS_MARQUEE = &H8
Private Const PBS_SMOOTH = &H1
Private Const PBS_SMOOTHREVERSE = &H10
Private Const PBS_VERTICAL = &H4
 
' Progress Bar States
Private Const PBST_NORMAL = 1
Private Const PBST_ERROR = 2
Private Const PBST_PAUSED = 3
 
' System Functions
Private Declare Sub CopyMemory Lib "kernel32" _
    Alias "RtlMoveMemory" ( _
    Destination As Any, Source As Any, ByVal length As Long)
 
' Window Functions
Private Declare Function GetActiveWindow Lib "user32" _
    () As Long
 
Private Declare Function SetWindowText Lib "user32" _
    Alias "SetWindowTextA" ( _
    ByVal hWnd As Long, ByVal lpString As String) As Long
 
' Dialog Functions
Private Declare Function DialogBoxIndirectParam Lib "user32" _
    Alias "DialogBoxIndirectParamA" ( _
    ByVal hInstance As Long, ByVal lpTemplate As Long, _
    ByVal hWndParent As Long, ByVal lpDialogFunc As Long, _
    ByVal dwInitParam As Long) As Long
 
Private Declare Function SetDlgItemText Lib "user32" _
    Alias "SetDlgItemTextA" ( _
    ByVal hDlg As Long, ByVal nIDDlgItem As Long, _
    ByVal lpString As String) As Long
    
Private Declare Function SendDlgItemMessage Lib "user32" _
    Alias "SendDlgItemMessageA" ( _
    ByVal hDlg As Long, ByVal nIDDlgItem As Long, _
    ByVal wMsg As Long, ByVal wParam As Long, _
    ByVal lParam As Long) As Long
 
Private Declare Function EndDialog Lib "user32" _
    (ByVal hDlg As Long, ByVal nResult As Long) As Long
    
' Common Controls Functions
Private Declare Function InitCommonControlsEx Lib "COMCTL32" _
    (ByRef picce As tagINITCOMMONCONTROLSEX) As Long
 
'-----------------------------------------------------------------------
' Progress Bar Functions
'-----------------------------------------------------------------------
 
' This type is necessary to ensure the dialog template, item templates,
' and their associated variable-length arrays are contiguous in memory.
' The DLGITEMTEMPLATE structures must be aligned on DWORD boundaries.
' The variable-length arrays must be aligned on WORD boundaries.
'
' Fixed-length byte arrays are used for the DLGITEMTEMPLATE class
' entries because VBA dynamic arrays would store a pointer in the UDT
' rather than the actual data. Titles are left blank in the template for
' convenience, to avoid alignment issues and conversion from BSTR to
' LPSTR. These can be set after the dialog is initialized.
 
Private Type DLG                     ' Length Padding Offset
    style As Long                    '      4       0      4
    extendedStyle As Long            '      4       0      8
    cdit As Integer                  '      2       0     10
    x As Integer                     '      2       0     12
    y As Integer                     '      2       0     14
    cx As Integer                    '      2       0     16
    cy As Integer                    '      2       0     18
    menu As Integer                  '      2       0     20
    class As Integer                 '      2       0     22
    title As Integer                 '      2       0     24
    
    progressStyle As Long            '      4       0     28
    progressExtendedStyle As Long    '      4       0     32
    progressX As Integer             '      2       0     34
    progressY As Integer             '      2       0     36
    progressCX As Integer            '      2       0     38
    progressCY As Integer            '      2       0     40
    progressID As Integer            '      2       2     44
    progressClass(34) As Byte        '     34       4     80
    progressTitle As Integer         '      2       0     82
    progressCreationData As Integer  '      2       0     84
    
    buttonStyle As Long              '      4       0     88
    buttonExtendedStyle As Long      '      4       0     92
    buttonX As Integer               '      2       0     94
    buttonY As Integer               '      2       0     96
    buttonCX As Integer              '      2       0     98
    buttonCY As Integer              '      2       0    100
    buttonID As Integer              '      2       2    104
    buttonClass(4) As Byte           '      4       0    108
    buttonTitle As Integer           '      2       0    110
    buttonCreationData As Integer    '      2       0    112
End Type
 
 
Public Function CreateProgressDialog()
    ' Build the dialog template.
    Dim template As DLG
    
    ' Check for the correct length. Only tested in 32-bit Office.
    Debug.Assert LenB(template) = 112
    
    template.style = DS_MODALFRAME Or WS_POPUP Or WS_BORDER Or _
                     WS_SYSMENU Or WS_CAPTION Or DS_CENTER
    template.extendedStyle = 0
    template.cdit = 2
    template.x = 200
    template.y = 200
    template.cx = 200
    template.cy = 49
    template.menu = 0
    template.class = 0
    template.title = 0
    
    ' Build the progress bar template.
    template.progressStyle = WS_CHILD Or WS_VISIBLE Or PBS_SMOOTH
    template.progressExtendedStyle = 0
    template.progressX = 7
    template.progressY = 7
    template.progressCX = 200 - 14
    template.progressCY = 14
    template.progressID = 10
    template.progressTitle = 0
    template.progressCreationData = 0
    
    Dim progressClass() As Byte
    progressClass = PROGRESS_CLASS
    CopyMemory template.progressClass(0), progressClass(0), 33
    
    ' Build the button template.
    template.buttonStyle = WS_CHILD Or WS_VISIBLE Or BS_DEFPUSHBUTTON
    template.buttonExtendedStyle = 0
    template.buttonX = 200 - 50 - 7
    template.buttonY = 28
    template.buttonCX = 50
    template.buttonCY = 14
    template.buttonID = IDCANCEL
    template.buttonClass(0) = &HFF
    template.buttonClass(1) = &HFF
    template.buttonClass(2) = &H80
    template.buttonCreationData = 0
    
    ' Use the active window as parent.
    Dim hWndParent As Long
    hWndParent = GetActiveWindow()
    
    ' Register the progress bar control class.
    Dim InitCtrlEx As tagINITCOMMONCONTROLSEX
    InitCtrlEx.dwSize = LenB(InitCtrlEx)
    InitCtrlEx.dwICC = ICC_PROGRESS_CLASS
    InitCommonControlsEx InitCtrlEx
    
    ' Create the dialog box.
    DialogBoxIndirectParam hInstance:=0, _
                           lpTemplate:=VarPtr(template), _
                           hWndParent:=hWndParent, _
                           lpDialogFunc:=AddressOf DlgProc, _
                           dwInitParam:=0
End Function
 
 
Private Function LOWORD(dw As Long) As Integer
    If dw And &H8000& Then
        LOWORD = dw Or &HFFFF0000
    Else
        LOWORD = dw And &HFFFF&
    End If
End Function
 
Private Function DlgProc(ByVal hWnd As Long, ByVal wMsg As Long, _
    ByVal wParam As Long, ByVal lParam As Long) As Long
    
    Select Case wMsg
    Case WM_INITDIALOG
        SetDlgItemText hWnd, IDCANCEL, "Cancel"
        SetWindowText hWnd, "Progress"
        
        ' Do a long running operation here, and check for cancel.
        SendDlgItemMessage hWnd, 10, PBM_STEPIT, 0, 0
        SendDlgItemMessage hWnd, 10, PBM_SETPOS, 50, 0
        
        ' Examples of different status states.
        'SendDlgItemMessage hWnd, 10, PBM_SETSTATE, PBST_ERROR, 0
        'SendDlgItemMessage hWnd, 10, PBM_SETSTATE, PBST_PAUSED, 0
        
        DlgProc = 1
        Exit Function
        
    Case WM_COMMAND
        Select Case LOWORD(wParam)
        Case IDOK
        Case IDCANCEL
            EndDialog hWnd, 0
            DlgProc = 1
        End Select
        Exit Function
        
    Case WM_CLOSE
        EndDialog hWnd, 0
        DlgProc = 1
        Exit Function
        
    End Select
    DlgProc = 0
End Function
Этот пример показывает как создать диалог для ожидания выполнения каких-то действий с прогрессбаром. Больше ничего в интернете нет вообще. Ещё раз убеждаюсь как в интернете сложно найти хоть что-то для VB6...
1
972 / 633 / 75
Регистрация: 08.02.2017
Сообщений: 2,480
Записей в блоге: 1
17.11.2023, 19:03 14
Цитата Сообщение от HackerVlad Посмотреть сообщение
Создать папку и попробовать ввести китайские иероглифы, в версии 2.5 должно работать и без манифеста, так как сам по себе диалог выбора папки стилизует окно, я говорил уже об этом
В 2.0 китайская папка не создается вообще ("ошибка создания папки"), в 2.5 создется.
1
958 / 570 / 40
Регистрация: 10.09.2021
Сообщений: 2,382
17.11.2023, 21:34  [ТС] 15
testuser2, спасибо большое, это как раз то, что я и хотел услашть)

Добавлено через 37 секунд
Всё так и должно быть, как я и думал, в VBA тоже работает значит)

Добавлено через 45 секунд
И без манифеста даже, как видишь, учитывая что майкрософтовское диалоговое окно выбора папки и так уже стилизует окно.

Добавлено через 4 минуты
Цитата Сообщение от testuser2 Посмотреть сообщение
Я так понимаю там также можно задать папку, на которую будет автоматичеки проматываться дерево?
Где там? Конечно можно.

Добавлено через 3 минуты
testuser2, а что ты используешь в качестве hwnd в VBA? Учитывая, что в VBA вроде как и нет в помине hwnd... Просто пишешь ноль? Например в моей функции вызова диалога выбора папки!? Или GetActiveWindow вызываешь, как в примере выше?

Добавлено через 1 минуту
Или GetForegroundWindow может...
0
972 / 633 / 75
Регистрация: 08.02.2017
Сообщений: 2,480
Записей в блоге: 1
18.11.2023, 05:38 16
Цитата Сообщение от HackerVlad Посмотреть сообщение
а что ты используешь в качестве hwnd в VBA? Учитывая, что в VBA вроде как и нет в помине hwnd... Просто пишешь ноль? Например в моей функции вызова диалога выбора папки!? Или GetActiveWindow вызываешь, как в примере выше?
В excel vba есть Application.Hwnd или Windows(1).Hwnd, hwnd формы можно получить с помощью GetActiveWindow или GetForegroundWindow или FindWindow.

Добавлено через 8 минут
Для определения размеров экрана я сделал процедуру
Visual Basic
1
2
3
4
5
6
7
8
Public Sub GetScreenSizes(screenWidth As Long, screenHeight As Long)
    Dim hDC As LongPtr
    ' Определяем размеры экрана
    hDC = GetDC(0)
    screenWidth = GetDeviceCaps(hDC, HORZRES) 'Screen.Width / Screen.TwipsPerPixelX
    screenHeight = GetDeviceCaps(hDC, VERTRES) 'Screen.Height / Screen.TwipsPerPixelY
    ReleaseDC 0, hDC
End Sub
1
958 / 570 / 40
Регистрация: 10.09.2021
Сообщений: 2,382
18.11.2023, 08:55  [ТС] 17
testuser2, спасибо за новые знания.
То есть там нет даже коллекции Screen. ???

Добавлено через 25 минут
testuser2, приходится наверное всегда немного переделывать и слегка переписывать при переносе кодов с vb6 на vba
0
972 / 633 / 75
Регистрация: 08.02.2017
Сообщений: 2,480
Записей в блоге: 1
18.11.2023, 09:06 18
HackerVlad, да какие знания, это просто особенности объектной модели. В Экселе одна объектная модель, в Ворде другая, в Автокаде 3я, в Корелдро 4я. Над каждой моделью работала отдельная группа разработчиков, даже взять модель Экселя - там все досконально продумано, и Ворд - гораздо хуже продумано, очень мало событий и т.д. У VB6 своя модель, в которой еть Screen, Timer.. Большинство этих функций легко заменить WinApi, c рисованием на форме конено посложнее. VBA это вообще сфера непрофессиональной и полупрофессиональной разработки, кто туда только не лезет, студенты, разные непонятные люди со тороны (типо меня), также это рзные инженеры, экономисты, медики, сфера бизнеса. В основном это что-то где-то быстренько посчитать в Экселе, подвести статистику или обработать текстовые данные. Был недавно биоинженер на другом форуме, интересные задачки у него были. Есть конечно отдельный раздел по Access там уже движуха ближе к профессиональной разработке приложений, там уже больше потребность во всяких кнопках и украшательствах (как ты показывал)
1
958 / 570 / 40
Регистрация: 10.09.2021
Сообщений: 2,382
18.11.2023, 09:09  [ТС] 19
Цитата Сообщение от testuser2 Посмотреть сообщение
да какие знания
ну если я по VBA ничего не знаю вообще... поэтому и спрашиваю у тебя иногда...
0
958 / 570 / 40
Регистрация: 10.09.2021
Сообщений: 2,382
18.11.2023, 09:25  [ТС] 20
Итак, вернёмся к тебе InputBox. Оказывается, в msvbvm60.dll есть функция под названием rctInputBox, исходный код функции InputBox в интернете я так и не нашёл, разве что дизассемблированный на ассемблере, там трудно что-то понять вообще. Но зато я понял каким образом создаётся сам этот InputBox. Он создаётся с помощью обычной функции создания диалогового окна на основе шаблона из ресурсов. А это значит, что в ресурсах файла msvbvm60.dll есть описанный InputBox.

С помощью программы Resource Hacker я выковырял из msvbvm60.dll этот самый заветный InputBox! И вот что сказано в ресурсах (ресурс Dialog/4031/1033):

Код
4031 DIALOG 55, 22, 238, 74
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION ""
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
FONT 9, "MS Shell Dlg"
{
   CONTROL "", 4901, STATIC, SS_LEFT | SS_NOPREFIX | WS_CHILD | WS_VISIBLE | WS_GROUP, 6, 6, 178, 45 
   CONTROL "", 4900, EDIT, ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 6, 56, 226, 12 
   CONTROL "OK", 1, BUTTON, BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 192, 6, 40, 14 
   CONTROL "Cancel", 2, BUTTON, BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 192, 23, 40, 14 
   CONTROL "&Help", 4902, BUTTON, BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 192, 40, 40, 14 
}
Тот самый InputBox появляется у нас со всеми прописанными координатами.
Миниатюры
Как создать на VB6 уникодный InputBox? Чтобы при вводе в InputBox можно было получать китайские иероглифы и так далее  
1
18.11.2023, 09:25
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
18.11.2023, 09:25
Помогаю со студенческими работами здесь

Как создать массив строк, чтобы их можно было как возвращать, так и изменять?
Здравствуйте. У меня следующая проблема: Вот так записан массив переменных string класса: ...

Создать класс из процедуры так, чтобы в нём при вызове можно было менять направление отсчёта счётчика цикла
Могу-ли я создать класс из процедуры так, чтобы в нём при вызове можно было менять направление...

Как создать файл DLL так, чтобы его можно было подключить к VBA Excel?
Пытаясь научиться подключать к VBA хотя бы самую тривиальную функцию на C++. Для примера написал...

Как можно сделать так чтобы при вводе пароля в TextBox1-е появлялись звёздочки?
Уважаемые программеры я создал форму где вводится пароль в TextBox1-е, но пароль в нём видна. Как...

Как правильно зациклить программу чтобы выходить из неё можно было при вводе "exit"
Здравствуйте, как правильно зациклить программу чтобы выходить из неё можно было при вводе "exit"...

Как сделать так чтобы при нажатии на picturebox1 можно было двигать форму по окну Windows?
как сделать так чтобы при нажатии на picturebox1 можно было двигать форму по окну Windows ...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru