Форум программистов, компьютерный форум, киберфорум
Visual Basic
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.60/2086: Рейтинг темы: голосов - 2086, средняя оценка - 4.60
18 / 18 / 0
Регистрация: 27.12.2018
Сообщений: 9
30.07.2022, 12:57
Студворк — интернет-сервис помощи студентам
Maxi v1.0.
Развернуть код...
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
Option Explicit
Dim strD(100) As String, nt(8) As Integer
Dim bd(8, 8) As Integer, av(64) As Integer, out(64) As Integer, dat(64) As Integer
Dim i As Byte, j As Integer, comp As Integer, man As Integer, arr As Byte, counter As Byte
 
Private Sub Form_Load()
Dim k As Integer, p1 As Integer, pc As Integer
' данные типа DATA
nt(1) = 48: nt(2) = 51: nt(3) = 53: nt(4) = 54: nt(5) = 56: nt(6) = 58: nt(7) = 60: nt(8) = 61
dat(1) = 15: dat(2) = 10: dat(3) = 9: dat(4) = 9: dat(5) = 8: dat(6) = 8: av(7) = 7: av(8) = 7
dat(9) = 7: dat(10) = 6: dat(11) = 6: dat(12) = 6: dat(13) = 5: dat(14) = 5: dat(15) = 5: dat(16) = 5
dat(17) = 4: dat(18) = 4: dat(19) = 4: dat(20) = 4: dat(21) = 3: dat(22) = 3: dat(23) = 3: dat(24) = 3
dat(25) = 3: dat(26) = 2: dat(27) = 2: dat(28) = 2: dat(29) = 2: dat(30) = 2: dat(31) = 2: dat(32) = 1
dat(33) = 1: dat(34) = 1: dat(35) = 1: dat(36) = 1: dat(37) = 0: dat(38) = 0: dat(39) = 0: dat(40) = 0
dat(41) = 0: dat(42) = 0: dat(43) = -1: dat(44) = -1: dat(45) = -1: dat(46) = -1: dat(47) = -1: dat(48) = -2
dat(49) = -2: dat(50) = -2: dat(51) = -2: dat(52) = -3: dat(53) = -3: dat(54) = -3: dat(55) = -4: dat(56) = -4
dat(57) = -4: dat(58) = -5: dat(59) = -5: dat(60) = -6: dat(61) = -6: dat(62) = -7: dat(63) = -9: dat(64) = 100
 
'    генератор распределения чисел по столу
    For k = 1 To 64: av(k) = k: Next k
    For k = 64 To 1 Step -1: pc = dat(65 - k)
    Randomize (Timer)
    p1 = 1 + Int(k * Rnd(k))
    j = av(p1) - 1
    If p1 < k Then For i = p1 To k - 1: av(i) = av(i + 1): Next i
    i = Int(j / 8): j = j - 8 * i
    i = i + 1: j = j + 1
    bd(i, j) = pc: out((i * 8 + j) - 8) = pc
    Next k
    Call InfoTable
    imgCell((i * 8 + j) - 8).Picture = Maxi.ListImages("n150").Picture
    counter = 0
End Sub
 
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
Dim k As Byte, tmp As Integer, max As Integer, endGame As Integer
 
'ход человека
Select Case KeyCode
    Case 37      'влево
    imgCell((i * 8 + j) - 8).Picture = Maxi.ListImages("n" & bd(i, j)).Picture
        j = j - 1
        If j < 1 Then j = 8
    imgCell((i * 8 + j) - 8).Picture = Maxi.ListImages("n" & bd(i, j) + 50).Picture
    Case 39      'вправо
    imgCell((i * 8 + j) - 8).Picture = Maxi.ListImages("n" & bd(i, j)).Picture
        j = j + 1
        If j > 8 Then j = 1
    imgCell((i * 8 + j) - 8).Picture = Maxi.ListImages("n" & bd(i, j) + 50).Picture
    Case 13      'enter
        If bd(i, j) = 100 Then
            Exit Sub
        Else
            man = man + bd(i, j): lblMan.Caption = "Человек: " & man
            bd(i, j) = 100
            imgCell((i * 8 + j) - 8).Picture = Maxi.ListImages("n150").Picture
        End If
 
    'проверка на конец игры
    For k = 1 To 8: endGame = endGame + bd(k, j): Next k
    counter = counter + 1
        If counter = 32 Or endGame = 800 Then MsgBox "КОНЕЦ ИГРЫ !" & Chr$(10) & "Компьютер - " & comp & Chr$(10) & "Человек - " & man: End
 
    'ход машины
    Wait (1)
    max = -10
    For k = 1 To 8
        If max < bd(k, j) And bd(k, j) <> 100 Then tmp = k: max = bd(k, j)
    Next k
    comp = comp + bd(tmp, j): lblComp.Caption = "Компьютер: " & comp
    imgCell((i * 8 + j) - 8).Picture = Maxi.ListImages("n100").Picture
    i = tmp
    imgCell((i * 8 + j) - 8).Picture = Maxi.ListImages("n150").Picture
    bd(i, j) = 100
End Select
End Sub
 
'вывод на стол текущей позиции
Private Sub InfoTable()
    For arr = 1 To 64
        imgCell(arr).Picture = Maxi.ListImages("n" & out(arr)).Picture
    Next arr
End Sub
 
'вывд формы с описанием инры
Private Sub mnuHelp_Click()
    helpInfo.Visible = True
End Sub
 
'временная задержка для компа
Private Sub Timer1_Timer()
    Timer1.Interval = 0
End Sub
Public Sub Wait(seconds)
    Timer1.Enabled = True
    Me.Timer1.Interval = 1000 * seconds
    While Me.Timer1.Interval > 0
      DoEvents
    Wend
    Timer1.Enabled = False
End Sub
Миниатюры
Готовые решения и полезные коды на Visual Basic 6.0  
Вложения
Тип файла: zip Maxi.zip (22.2 Кб, 67 просмотров)
2
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
30.07.2022, 12:57
Ответы с готовыми решениями:

Продам готовые коды и решения на Visual Basic за 400 рублей
душу продаю:cry: Продам коды исходные на VB !!10 лет копил за 400р !!размер тока кодов 312метров там есть все ! мыло контакты удалены....

Коды на Visual Basic
Ребята всем привет,я начел изучать &quot;Visual Basic&quot;! Очень буду благодарен за коды по этому языку, очень интиресный язык)))! Бросайте сюда...

Вывод решения вместо Immediate в textbox (visual basic 6.0)
программа выводит решение в Immediate а я хочу разместить на форме text1 и что бы решение выводилось туда ,менял код менял не че не...

356
18 / 18 / 0
Регистрация: 27.12.2018
Сообщений: 9
06.08.2022, 12:37
3D Tic-Tac-Toe v1.1.
Развернуть код...
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
297
Option Explicit
Dim i As Integer, a As Integer, b As Integer, posn As Integer, no As Integer
Dim level As Byte, hod As Byte, m As Byte
Dim arr(27) As Integer: Dim brr(49) As Integer, g As Integer '(27 - кол-во ячеек, 49 - кол-во ходов)
Dim t As Byte, f As Byte, p As Byte, q As Byte, go As Byte
Dim row As String, cell As Byte
Dim sec As Byte, счетчик As Integer
Dim strLevel As String, strHod As String
Dim code1 As String, code2 As String
 
Private Sub Form_Load()  '============== загрузка стартовой заставки ============
    picTable.AutoRedraw = True
    picTable.ForeColor = 13526
    picTable.FontBold = True
    picTable.FontUnderline = True
    picTable.FontSize = 16
    picTable.Print ""
    picTable.Print "    3d Noughts and Crosses     "
    picTable.FontUnderline = False
    picTable.FontSize = 12
    picTable.ForeColor = 135
    picTable.Print ""
    picTable.Print "     Сюжет  игры  -  в  том,  чтобы"
    picTable.Print " собрать комплект линий столько,"
    picTable.Print " сколько Вы сможете. Компьютер"
    picTable.Print " также будет пытаться!"
    picTable.Print "     Считаются  все  прямые линии"
    picTable.Print " по  горизонтали,  вертикали   или"
    picTable.Print " диагонали.    Таких    возможных"
    picTable.Print " линий 49."
    picTable.ForeColor = 1754732
    picTable.Print "     Выберите уровень сложности:"
    picTable.Print ""
    picTable.Print "               первый ход делает -"
    picTable.Print ""
    picTable.Print ""
    picTable.ForeColor = 874732
    picTable.Print "              ===================="
    picTable.FontBold = False
    счетчик = 0
code1 = "14, 23, 05, 48, 46, 49, 47, 33, 28, 39, 36, 45, 43, 40, 37, 30, 31, 34, 42, 25, 01, 12, 09, 10, 19, 07, 03, 18, 21, 27, 16, 35, 44, 32, 29, 41, 38, 11, 20, 15, 17, 02, 08, 04, 26, 22, 06, 13, 24"
'code2 = "15, 23, 05, 13, 23, 11, 27, 19, 03, 07, 01, 21, 25, 09"
code2 = "15, 23, 05, 13, 17, 11, 27, 19, 03, 07, 01, 21, 25, 09, 02, 04, 06, 08, 10, 12, 14, 16, 18, 20, 22, 24, 26"
End Sub
 
Private Sub cmdLevel_Click(Index As Integer)   ' ======== выбор уровня игры ========
    If cmdLevel(0) Then level = 1: strLevel = "легкий"
    If cmdLevel(1) Then level = 2: strLevel = "средний"
    If cmdLevel(2) Then level = 3: strLevel = "сложный"
    lblInfo.Caption = "уровень - " & strLevel
End Sub
 
Private Sub cmdStep_Click(Index As Integer)   ' ======== право первого хода ========
    If cmdStep(0) Then m = 0: strHod = "человек"
    If cmdStep(1) Then m = 1: strHod = "комп"
    lblInfo.Caption = "уровень - " & strLevel & ", ходит - " & strHod
End Sub
 
Private Sub cmdPlay_Click() ' ======== кнопка GO ========
    picTable.Cls
    For i = 0 To 2
        cmdLevel(i).Visible = False
    Next i
    For i = 0 To 1
        cmdStep(i).Visible = False
    Next i
        cmdPlay.Visible = False
    For i = 0 To 9
        imgRowA(i).Visible = True
        imgRowB(i).Visible = True
        imgRowC(i).Visible = True
    Next i
    If m = 1 And level = 1 Then Call goComp1 ' ======== если первым играет Комп ========
    If m = 1 And level = 2 Then Call goComp2 ' ======== если первым играет Комп ========
    If m = 1 And level = 3 Then Call goComp3 ' ======== если первым играет Комп ========
End Sub
 
' ============================ ход человека - начало==================================
Private Sub imgRowA_Click(Index As Integer) ' ======== выбор row (ряд) и cell (ячейки) ========
    cell = Index: row = "A": posn = cell:           ' ======== posn позиция ячейки от 1 до 27 =======
    Call GSB8000 'ход человека
        If level = 1 Then Call goComp1
        If level = 2 Then Call goComp2
        If level = 3 Then Call goComp3
End Sub
Private Sub imgRowB_Click(Index As Integer)
    cell = Index: row = "B": posn = cell + 9
    Call GSB8000 'ход человека
        If level = 1 Then Call goComp1
        If level = 2 Then Call goComp2
        If level = 3 Then Call goComp3
End Sub
Private Sub imgRowC_Click(Index As Integer)
    cell = Index: row = "C": posn = cell + 18
    Call GSB8000 'ход человека
        If level = 1 Then Call goComp1
        If level = 2 Then Call goComp2
        If level = 3 Then Call goComp3
End Sub
' ============================ ход человека - конец==================================
 
 
' ============================ ход коспьютера легкий уровень - начало=========(проверено+++)=========================
Private Sub goComp1() '
    lblInfo.Caption = "I'm thinking..." '== комп думает
    sec = 1 '== время думания компа
    tmrTimer1.Interval = 1000
End Sub
Private Sub tmrTimer1_Timer() 'временная задержка для обдумывания компом хода
Dim counter As Byte
counter = 0 'счетчик
    sec = sec - 1 'уменьшение времени
        lblInfo.Caption = sec 'вывод на табло
    If sec = 0 Then 'если время кончилось
        lblInfo.Caption = "" 'затереть надпись
        tmrTimer1.Interval = 0 'отключить Timer
Randomize Timer 'генератор случайной позиции
            If arr(14) = 0 Then posn = 14: Call GSB8000: Exit Sub 'если козырная ячейка пуста. комп уже там
    Do While (counter < 1) 'цикл с условием, пока счетчик меньше единицы, крутим по кругу
        posn = Int(Rnd * 27) + 1 'поиск свободной ячейки
            If arr(posn) = 0 Then 'если да - занимаем
                Call GSB8000 'и обрабатываем
                counter = counter + 1 'увеличиваем счетчик
            End If
    Loop 'конец цикла
    End If
End Sub
 
 
' ============================ ход компьютера средний уровень - начало========(проверено)============
Private Sub goComp2()
    lblInfo.Caption = "I'm thinking..." '== комп думает
    sec = 2 '== время думания компа
    tmrTimer2.Interval = 1000
End Sub
Private Sub tmrTimer2_Timer()  ' ========= ход компа ============
Dim counter As Byte
counter = 0 'счетчик
    sec = sec - 1 'уменьшение времени
'        lblInfo.Caption = sec 'вывод на табло
If sec = 0 Then 'если время кончилось
'        lblInfo.Caption = "" 'затереть надпись
        tmrTimer2.Interval = 0 'отключить Timer
    If arr(14) = 0 Then posn = 14: Call GSB8000: Exit Sub 'если козырная ячейка пуста. комп уже там
        For f = 1 To 196 Step 4 'переберает все комбинации где сумма в линии = 1, т.е. ищет свою ячейку
        t = Val(Mid(code1, f, 2))
        If brr(t) = 1 Then Debug.Print "на линии один нолик": Call GSB7500: Exit Sub
        Next f
'        For f = 1 To 56 Step 4 'проверяет ключевые ячейки на пустоту
        For f = 1 To 108 Step 4 'проверяет ключевые ячейки на пустоту
        t = Val(Mid(code2, f, 2))
        If arr(t) = 0 Then posn = t: Debug.Print "ячейка пуста": Call GSB8000: Exit Sub
        Next f
End If
End Sub
 
 
' ================= ход компьютера сложный уровень - начало==========(периодически глючит что-то два первых Call)=======
Private Sub goComp3()
    lblInfo.Caption = "I'm thinking..." '== комп думает
    sec = 2 '== время думания компа
    tmrTimer3.Interval = 1000
End Sub
Private Sub tmrTimer3_Timer()  ' ========= ход компа ============
Dim counter As Byte
counter = 0 'счетчик
    sec = sec - 1 'уменьшение времени
'        lblInfo.Caption = sec 'вывод на табло
If sec = 0 Then 'если время кончилось
'        lblInfo.Caption = "" 'затереть надпись
        tmrTimer3.Interval = 0 'отключить Timer
    If arr(14) = 0 Then posn = 14: Call GSB8000: Exit Sub 'если козырная ячейка пуста. комп уже там
        For f = 1 To 196 Step 4 'проверка на наличие в линии два креста (две 4)
        t = Val(Mid(code1, f, 2))
        If brr(t) = 8 Then Debug.Print "линия занята двумя крестами": Call GSB7500: Exit Sub
        Next f
        For f = 1 To 196 Step 4 'проверка на наличие в линии два нолика (две 1)
        t = Val(Mid(code1, f, 2))
        If brr(t) = 2 Then Debug.Print "линия занята двумя ноликами": Call GSB7500: Exit Sub
        Next f
        For f = 1 To 196 Step 4 'переберает все комбинации где сумма в линии = 1, т.е. ищет свою ячейку
        t = Val(Mid(code1, f, 2))
        If brr(t) = 1 Then Debug.Print "линия занята одним ноликом": Call GSB7500: Exit Sub
        Next f
        For f = 1 To 108 Step 4 'проверяет ключевые ячейки на пустоту
        t = Val(Mid(code2, f, 2))
        If arr(t) = 0 Then posn = t: Debug.Print "ячейка пуста": Call GSB8000: Exit Sub
        Next f
End If
End Sub
 
 
Private Sub GSB7500()
Debug.Print "GSB7500", "brr("; t; ")="; brr(t)
    a = 0
    If t < 10 Then For p = t To t + 18 Step 9: a = a + (p And (a = 0 And arr(p) = 0)): Next p 'столбики 1,10,19; 2,11,20 ... 8,17,26; 9,18,27
    If t > 9 And t < 19 Then q = ((t - 9) And t < 13) + ((t - 3) And (t < 16 And t > 12)) + ((t + 3) And t > 15): _
            For p = q To q + 7 Step 3: a = a + (p And (a = 0 And arr(p) = 0)): Next p '1,4,7; 2,5,8; 3,6,9; 10,13,16...20,23,26;21,24,27 вертикали
    If t > 18 And t < 28 Then q = (t - 19) * 3 + 1: For p = q To q + 2: a = a + (p And (a = 0 And arr(p) = 0)): Next p '1,2,3: 3,4,5: 7,8,9, 10,11,12...22,23,24:25,26,27 горизонталь
    If t > 27 And t < 31 Then q = t - 27: For p = q To q + 24 Step 12: a = a + (p And (a = 0 And arr(p) = 0)): Next p 'линии 1,13,25; 2,14,25; 3,15,27
    If t > 30 And t < 34 Then q = (t - 31) * 3 + 1: For p = q To q + 20 Step 10: a = a + (p And (a = 0 And arr(p) = 0)): Next p 'диагонали 1,11,21: 4,14,24; 7,17,27
    If t > 33 And t < 37 Then q = t - 27: For p = q To q + 12 Step 6: a = a + (p And (a = 0 And arr(p) = 0)): Next p 'линии 7,13,19; 8,14,20; 9,15,21
    If t > 36 And t < 40 Then q = (t - 37) * 3 + 3: For p = q To q + 16 Step 8: a = a + (p And (a = 0 And arr(p) = 0)): Next p 'диаголнали 3,11,19; 6,14,22; 9,17,25
    If t > 39 And t < 43 Then q = (t - 40) * 9 + 1: For p = q To q + 8 Step 4: a = a + (p And (a = 0 And arr(p) = 0)): Next p 'диагонали 1,5,9; 10,14,18; 19,23,27
    If t > 42 And t < 46 Then q = (t - 43) * 9 + 3: For p = q To q + 4 Step 2: a = a + (p And (a = 0 And arr(p) = 0)): Next p 'диагонали 3,5,7; 12,14,16; 21,23,25
    If t = 46 Then For p = 1 To 27 Step 13: a = a + (p And (a = 0 And arr(p) = 0)): Next p 'линия 1,14,27 (проверка на первое пустое место, если все занято = 0)
    If t = 47 Then For p = 3 To 25 Step 11: a = a + (p And (a = 0 And arr(p) = 0)): Next p 'линия 3,14,25 (проверка на первое пустое место, если все занято = 0)
    If t = 48 Then For p = 7 To 21 Step 7: a = a + (p And (a = 0 And arr(p) = 0)): Next p 'линия 7,14,21 (проверка на первое пустое место, если все занято = 0)
    If t = 49 Then For p = 9 To 19 Step 5: a = a + (p And (a = 0 And arr(p) = 0)): Next p 'линия 9,14,19 (проверка на первое пустое место, если все занято = 0)
'    a = a + (p And (a = 0 And arr(p) = 0)): Next p
    'a = (a Or a = 0)
    posn = a: 'arr(a) = 1
'            Debug.Print "t = " & t, "cell = " & a
    Call GSB8000
End Sub
 
 
 
 
Private Sub GSB8000()
счетчик = счетчик + 1
    If posn < 10 Then row = "A": cell = posn                            '|  выделелние из позиции (posn)
    If posn > 9 And posn < 19 Then row = "B": cell = posn - 9   '|  ряда (row) и
    If posn > 18 Then row = "C": cell = posn - 18                      '| ячейки в ряде (cell)
    lblInfo.Caption = "выбрано - " & row & "-" & cell & " (" & posn & ")" ' вывести на табло данные
        If arr(posn) <> 0 Then lblInfo.Caption = "ячейка " & row & "-" & cell & " (" & posn & ")" & " занята": Exit Sub 'проверить на пустую ячейку
    If m = 0 Then arr(posn) = 4  'если да поставить крест
    If m = 1 Then arr(posn) = 1  ' или нолик
Debug.Print счетчик; ". "; posn, m, arr(posn)
 
        If m = 0 And row = "A" Then imgRowA(cell).Picture = LoadPicture("img" & cell & "x.bmp") ' вывод
        If m = 1 And row = "A" Then imgRowA(cell).Picture = LoadPicture("img" & cell & "o.bmp") ' на экран
        If m = 0 And row = "B" Then imgRowB(cell).Picture = LoadPicture("img" & cell & "x.bmp") ' рисунок
        If m = 1 And row = "B" Then imgRowB(cell).Picture = LoadPicture("img" & cell & "o.bmp") ' крестика
        If m = 0 And row = "C" Then imgRowC(cell).Picture = LoadPicture("img" & cell & "x.bmp") ' или
        If m = 1 And row = "C" Then imgRowC(cell).Picture = LoadPicture("img" & cell & "o.bmp") ' нолика
        
        b = 1 'счетчик ======================================================= 1...9
        For p = 1 To 9 'проверка столбиков
            brr(b) = arr(p) + arr(p + 9) + arr(p + 18) 'сложить все ячейки - в массив
            b = b + 1 'и увеличить счетчик
        Next p
        For p = 1 To 21 'проверка вертикальных линий во всех рядах ==================== 10...18
            If p = 4 Then p = 10
            If p = 13 Then p = 19
            brr(b) = arr(p) + arr(p + 3) + arr(p + 6) 'сложить все ячейки - в массив
            b = b + 1 'и увеличить счетчик
        Next p
        For p = 1 To 25 Step 3 'проверка горизонтальных линий во всех рядах ============= 19...27
            brr(b) = arr(p) + arr(p + 1) + arr(p + 2) 'сложить все ячейки - в массив
            b = b + 1 'и увеличить счетчик
        Next p
        For p = 1 To 3 'левая косая линия ========================================= 28...30
            brr(b) = arr(p) + arr(p + 12) + arr(p + 24) 'сложить все ячейки - в массив
            b = b + 1 'и увеличить счетчик
        Next p
        For p = 1 To 7 Step 3 'тыл - косая,  внутренняя - косая, фронт - косая ============== 31...33
            brr(b) = arr(p) + arr(p + 10) + arr(p + 20) 'сложить все ячейки - в массив
            b = b + 1 'и увеличить счетчик
        Next p
        For p = 7 To 9 'левая косая линия ======================================== 34...36
            brr(b) = arr(p) + arr(p + 6) + arr(p + 12) 'сложить все ячейки - в массив
            b = b + 1 'и увеличить счетчик
        Next p
        For p = 3 To 9 Step 3 'тыльная косая, внутреняя - косая, фронт - косая ============= 37...39
            brr(b) = arr(p) + arr(p + 8) + arr(p + 16) 'сложить все ячейки - в массив
            b = b + 1 'и увеличить счетчик
        Next p
        For p = 1 To 19 Step 9 'диогональные на плостостях рядов ====================== 40...42
            brr(b) = arr(p) + arr(p + 4) + arr(p + 8) 'сложить все ячейки - в массив
            b = b + 1 'и увеличить счетчик
        Next p
        For p = 3 To 21 Step 9 'диогональные на плостостях рядов ====================== 43...45
            brr(b) = arr(p) + arr(p + 2) + arr(p + 4) 'сложить все ячейки - в массив
            b = b + 1 'и увеличить счетчик
        Next p
            brr(b) = arr(1) + arr(14) + arr(27) 'внутренняя диагональ ======================= 44
            b = b + 1 'и увеличить счетчик
            brr(b) = arr(3) + arr(14) + arr(25) 'внутренняя диагональ ======================= 45
            b = b + 1 'и увеличить счетчик
            brr(b) = arr(7) + arr(14) + arr(21) 'внутренняя диагональ ======================= 46
            b = b + 1 'и увеличить счетчик
            brr(b) = arr(9) + arr(14) + arr(19) 'внутренняя диагональ ======================= 47
            b = b + 1 'и увеличить счетчик
            go = go + 1 'текущий номер хода
                If go = 27 Then Call GameOver 'если все занято - конец игры
            m = Abs(m - 1) 'инвертор простой (меняет ход игроков)
End Sub
 
Private Sub GameOver()
    a = 0: b = 0
    For f = 1 To 49
        If brr(f) = 3 Then a = a + 1 'линии компьютера
        If brr(f) = 12 Then b = b + 1 'линии человека
    Next f
        MsgBox "Компьютер - " & a & Chr$(10) & "Человек - " & b: End
End Sub
Миниатюры
Готовые решения и полезные коды на Visual Basic 6.0  
Вложения
Тип файла: zip TicTacToe.zip (61.3 Кб, 60 просмотров)
2
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18031 / 7734 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16
01.11.2022, 20:25  [ТС]
Коллекция must-have фиксов и полезняшек для VB6:

Большинство устанавливается запуском батника от имени Администратора (правая кнопка мыши, контекстное меню).
В папках есть Readme. Не ленитесь прочитать.

1) VB6-IDE-Install-Fix (Dragokas). Ставится ДО установки IDE.
Позволяет успешно закончить установку IDE на Windows 8+.
Устраняет проблему с отсутствующей регистрацией MSADC.

2) IDE_Window_Fix (Dragokas & The Trick).
Расширение. Позволяет автоматически разворачивать главное окно проекта на весь экран.
Проблема есть только на Windows 10+.

3) VB6IDEMouseWheelAddin (автор: ?)
Расширение. Позволяет добавить поддержку прокрутки мышью в IDE.

4) MSCOMCTL-Fix
Позволяет корректно установить компонент Microsoft MSCOMCTL.
Предоставляет доступ с некоторому кол-ву популярных контролов (без юникод поддержки).

5) Save_VB6_IDE_Settings (Dragokas)
Позволяет сделать бекап вашей темы подсветки.
В коплекте есть твик с моей любимой темой.

6) VB6-Settings-Fix (Dragokas)
Твик дефоловых настроек IDE.
Примените, если у вас куда-то внезапно потерялись кнопки или "поехали" окна.

7) VBP_Runas (Dragokas)
Добавляет в контекстное меню файлов .vbp пункт "Запуск от имени Администратора".
Вложения
Тип файла: zip Fix_VB6.zip (910.6 Кб, 66 просмотров)
8
 Аватар для Mikle Quits
766 / 283 / 17
Регистрация: 21.01.2023
Сообщений: 436
26.01.2023, 10:15
Случайное число, заменитель RND.
Где-то в модуле размещаем код:
Visual Basic
1
2
3
4
5
6
7
8
9
10
Dim Ri As Double
 
Public Function Rand() As Single
  Ri = Ri * (1.241 + (Ri > 983732.3)) + 1.737
  Rand = Ri - Int(Ri)
End Function
 
Public Sub RandInit(ByVal R As Single)
  Ri = R
End Sub
Вместо Randomize используем RandInit.
Вместо RND используем Rand.
Будучи скомпилированный в Native Code работает в 5-7 раз быстрее, чем RND.
Так же даёт более качественное распределение. Чтобы понять, о чём я пишу, попробуйте заполнить изображение 256*256 случайными цветами по формуле &HFFFFFF * RND, а потом &HFFFFFF * Rand.
6
 Аватар для Mikle Quits
766 / 283 / 17
Регистрация: 21.01.2023
Сообщений: 436
27.01.2023, 09:54
Быстрая нерекурсивная заливка однотонной части изображения другим цветом.
Изображение должно быть в двумерном массиве типа Long. Приложенный пример (исходник и EXE) загружает изображение в такой массив из файла. Кликом ЛКМ в произвольном месте мы запускаем заливку случайным цветом от данной точки, ПКМ восстанавливает исходное изображение.

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
Option Explicit
 
Public Sub Fill(Ar() As Long, ByVal X As Long, ByVal Y As Long, ByVal Col As Long)
  Dim dX As Long, dY As Long
  Dim bCol As Long
  Dim pX() As Long, pY() As Long
  Dim Ptr As Long, Cnt(1) As Long
  Dim C As Long, n As Long
 
  bCol = Ar(X, Y)
  If bCol = Col Then Exit Sub
  dX = UBound(Ar(), 1) + 1
  dY = UBound(Ar(), 2) + 1
  ReDim pX((dX + dY) * 4, 1)
  ReDim pY((dX + dY) * 4, 1)
  
  Cnt(Ptr) = 1
  pX(0, Ptr) = X
  pY(0, Ptr) = Y
  Do
    C = 0
    For n = 0 To Cnt(Ptr) - 1
      If pX(n, Ptr) < dX - 1 Then
        If Ar(pX(n, Ptr) + 1, pY(n, Ptr)) = bCol Then
          pX(C, 1 - Ptr) = pX(n, Ptr) + 1
          pY(C, 1 - Ptr) = pY(n, Ptr)
          Ar(pX(C, 1 - Ptr), pY(C, 1 - Ptr)) = Col
          C = C + 1
        End If
      End If
      If pY(n, Ptr) < dY - 1 Then
        If Ar(pX(n, Ptr), pY(n, Ptr) + 1) = bCol Then
          pX(C, 1 - Ptr) = pX(n, Ptr)
          pY(C, 1 - Ptr) = pY(n, Ptr) + 1
          Ar(pX(C, 1 - Ptr), pY(C, 1 - Ptr)) = Col
          C = C + 1
        End If
      End If
      If pX(n, Ptr) > 0 Then
        If Ar(pX(n, Ptr) - 1, pY(n, Ptr)) = bCol Then
          pX(C, 1 - Ptr) = pX(n, Ptr) - 1
          pY(C, 1 - Ptr) = pY(n, Ptr)
          Ar(pX(C, 1 - Ptr), pY(C, 1 - Ptr)) = Col
          C = C + 1
        End If
      End If
      If pY(n, Ptr) > 0 Then
        If Ar(pX(n, Ptr), pY(n, Ptr) - 1) = bCol Then
          pX(C, 1 - Ptr) = pX(n, Ptr)
          pY(C, 1 - Ptr) = pY(n, Ptr) - 1
          Ar(pX(C, 1 - Ptr), pY(C, 1 - Ptr)) = Col
          C = C + 1
        End If
      End If
    Next n
    If C = 0 Then Exit Do
    Ptr = 1 - Ptr
    Cnt(Ptr) = C
  Loop
End Sub
Вложения
Тип файла: zip Fill.zip (25.1 Кб, 68 просмотров)
3
 Аватар для Mikle Quits
766 / 283 / 17
Регистрация: 21.01.2023
Сообщений: 436
29.01.2023, 19:38
Качественный ресайз изображения.

Ещё один фильтр обработки изображений. Это более качественное масштабирование, чем, скажем, билинейная фильтрация.
Как и в предыдущем примере, фильтр находится в отдельном модуле и не имеет никаких зависимостей.
Работает с образом изображения в 2D массиве.
Позволяет указывать независимые коэффициенты масштабирования по осям X и Y.
В приложенном примере модуль с фильтром и форма с кодом, демонстрирующим применение фильтра, кликайте по форме в произвольном месте, и смотрите на результат, имейте ввиду, что скомпилированная программа работает гораздо быстрее, чем из IDE.

Код фильтра:
Кликните здесь для просмотра всего текста
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
'Ресайзинг изображений
'Написал Ильин Михаил (Mikle).
 
Option Explicit
 
Private Type Col
  a As Long
  r As Long
  g As Long
  b As Long
End Type
 
'Масштабирует содержимое первого массива во второй
'Массивы должны быть двумерными, с базой от 0, типа Long
'При большой разнице в размерах массивов (несколько тысяч) может быть переполнение
 
Public Sub RGBResize(ArIn() As Long, ArOut() As Long)
  Dim XX As Long, YY As Long
  Dim X As Long, Y As Long
  Dim iXX As Long, iYY As Long
  Dim iX As Long, iY As Long
  Dim cX As Long, cY As Long, cXY As Long, cc As Long
  Dim pIn As Long, pOut As Long, p As Long
  Dim ikX() As Long, ikY() As Long
  Dim kX() As Long, kY() As Long
  Dim wIn As Long, wOut As Long
  Dim hIn As Long, hOut As Long
  Dim c As Col, c2 As Col
 
  wIn = UBound(ArIn, 1) + 1
  hIn = UBound(ArIn, 2) + 1
  wOut = UBound(ArOut, 1) + 1
  hOut = UBound(ArOut, 2) + 1
  cX = (wIn - 1) \ wOut + 2
  cY = (hIn - 1) \ hOut + 2
  X = cX * wOut - 1
  Y = cY * hOut - 1
  ReDim ikX(X) As Long, ikY(Y) As Long
  ReDim kX(X) As Long, kY(Y) As Long
 
  If wIn >= wOut Then
    cXY = wIn
    pIn = 0: pOut = 1: p = 0
    Do
      cc = pOut * wIn - pIn * wOut
      If cc >= wOut Then
        kX(p) = wOut
      Else
        kX(p) = cc
        ikX(p) = pIn
        p = pOut * cX
        pOut = pOut + 1
        kX(p) = wOut - cc
      End If
      ikX(p) = pIn
      pIn = pIn + 1
      If pIn >= wIn Then Exit Do
      p = p + 1
    Loop
  Else
    cXY = wOut
    For X = 0 To wOut - 1
      p = X * 2
      kX(p + 1) = X * (wIn - 1) Mod (wOut - 1)
      ikX(p) = X * (wIn - 1) \ (wOut - 1)
      kX(p) = wOut - kX(p + 1)
      ikX(p + 1) = (ikX(p) + 1) Mod wIn
    Next X
  End If
 
  If hIn >= hOut Then
    cXY = cXY * hIn
    pIn = 0: pOut = 1: p = 0
    Do
      cc = pOut * hIn - pIn * hOut
      If cc >= hOut Then
        kY(p) = hOut
      Else
        kY(p) = cc
        ikY(p) = pIn
        p = pOut * cY
        pOut = pOut + 1
        kY(p) = hOut - cc
      End If
      ikY(p) = pIn
      pIn = pIn + 1
      If pIn >= hIn Then Exit Do
      p = p + 1
    Loop
  Else
    cXY = cXY * hOut
    For Y = 0 To hOut - 1
      p = Y * 2
      kY(p + 1) = Y * (hIn - 1) Mod (hOut - 1)
      ikY(p) = Y * (hIn - 1) \ (hOut - 1)
      kY(p) = hOut - kY(p + 1)
      ikY(p + 1) = (ikY(p) + 1) Mod hIn
    Next Y
  End If
 
  iYY = 0
  For YY = 0 To hOut - 1
    iXX = 0
    For XX = 0 To wOut - 1
      c = RGBToCol(0)
      iY = iYY
      For Y = 1 To cY
        iX = iXX
        For X = 1 To cX
          c2 = RGBToCol(ArIn(ikX(iX), ikY(iY)))
          ColMulVal c2, kX(iX) * kY(iY)
          ColAddCol c, c2
          iX = iX + 1
        Next X
        iY = iY + 1
      Next Y
      ColMulVal c, 1 / cXY
      ArOut(XX, YY) = ColToRGB(c)
      iXX = iXX + cX
    Next XX
    iYY = iYY + cY
  Next YY
End Sub
 
'Вспомогательные процедуры
 
Private Sub ColAddCol(Dest As Col, Src As Col)
  Dest.r = Dest.r + Src.r
  Dest.g = Dest.g + Src.g
  Dest.b = Dest.b + Src.b
End Sub
 
Private Sub ColMulVal(Dest As Col, v As Single)
  Dest.r = Dest.r * v
  Dest.g = Dest.g * v
  Dest.b = Dest.b * v
End Sub
 
Private Function ColToRGB(c As Col) As Long
  ColToRGB = c.r * &H10000 + c.g * &H100 + c.b
End Function
 
Private Function RGBToCol(ByVal c As Long) As Col
  RGBToCol.r = (c And &HFF0000) \ &H10000
  RGBToCol.g = (c And &HFF00&) \ &H100
  RGBToCol.b = c And &HFF
End Function
Вложения
Тип файла: zip Resize.zip (41.2 Кб, 78 просмотров)
4
Модератор
10048 / 3894 / 883
Регистрация: 22.02.2013
Сообщений: 5,847
Записей в блоге: 79
04.02.2023, 11:37
Стеклянная форма.



В архиве 2 примера "стеклянной" формы. glass_layered - основан на слоеных окнах и работает при отключенном DWM, glass_magapi - основан на Magnification API и работает с Win7 и выше.
Вложения
Тип файла: zip Glass.zip (24.5 Кб, 79 просмотров)
5
Модератор
10048 / 3894 / 883
Регистрация: 22.02.2013
Сообщений: 5,847
Записей в блоге: 79
04.02.2023, 11:47
Получение списка методов VB-объекта.

Метод возвращает список всех пользовательских публичных методов VB-объекта.

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
Option Explicit
Option Base 0
 
Public Enum PTR
    [_]
End Enum
 
Private Declare Function GetMem1 Lib "msvbvm60" ( _
                         ByRef Source As Any, _
                         ByRef Dest As Any) As Long
Private Declare Function GetMem4 Lib "msvbvm60" ( _
                         ByRef Source As Any, _
                         ByRef Dest As Any) As Long
Private Declare Function GetMemPtr Lib "msvbvm60" Alias "GetMem4" ( _
                         ByRef Source As Any, _
                         ByRef Dest As Any) As Long
Private Declare Function GetMem2 Lib "msvbvm60" ( _
                         ByRef Source As Any, _
                         ByRef Dest As Any) As Long
Private Declare Function lstrlenA Lib "kernel32" ( _
                         ByRef lpString As Any) As Long
Private Declare Function SysAllocStringByteLen Lib "oleaut32" ( _
                         ByRef psz As Any, _
                         ByVal lSize As Long) As String
 
' // Get list of VB6 object methods
Public Property Get ListOfMethods( _
                    ByVal cObj As Object) As String()
    Dim sRet()      As String
    Dim lIndex      As Long
    Dim lCount      As Long
    Dim pObjInfo    As PTR
    Dim pPubDesc    As PTR
    Dim pPrivDesc   As PTR
    Dim pMembers    As PTR
    Dim pMethDesc   As PTR
    Dim pVtbl       As PTR
    Dim lMethods    As Long
    Dim pNames      As PTR
    Dim pName       As PTR
    Dim lMethOffset As Long
    Dim lPropCount  As Long
    Dim lFlags      As Long
    
    GetMemPtr ByVal ObjPtr(cObj), pVtbl
    GetMemPtr ByVal pVtbl - 4, pObjInfo
    GetMemPtr ByVal pObjInfo + &H18, pPubDesc
    GetMemPtr ByVal pObjInfo + &HC, pPrivDesc
    GetMemPtr ByVal pPubDesc + &H20, pNames
    
    If pPrivDesc = 0 Then
        Exit Property
    End If
    
    GetMemPtr ByVal pPrivDesc + &H18, pMembers
    GetMem2 ByVal pPubDesc + &H1C, lMethods
    
    If lMethods = 0 Then
        Exit Property
    End If
 
    For lIndex = 0 To lMethods - 1
        
        GetMemPtr ByVal pMembers, pMethDesc
 
        If pMethDesc Then
            
            GetMem2 ByVal pMethDesc + 2, lMethOffset
            
            If lMethOffset And 1 Then
                
                lMethOffset = lMethOffset And -2
                
                GetMemPtr ByVal pNames + lIndex * Len(pName), pName
                
                If lCount Then
                    If lCount > UBound(sRet) Then
                        ReDim Preserve sRet(lCount + 10)
                    End If
                Else
                    ReDim sRet(9)
                End If
                
                sRet(lCount) = SysAllocStringByteLen(ByVal pName, lstrlenA(ByVal pName))
                
                lCount = lCount + 1
                
            End If
 
        End If
        
        pMembers = pMembers + 4
        
    Next
    
    GetMem2 ByVal pPrivDesc + &H10, lPropCount
    GetMemPtr ByVal pPrivDesc + &H20, pMembers
    
    For lIndex = 0 To lPropCount - 1
        
        GetMemPtr ByVal pMembers, pMethDesc
        
        If pMethDesc Then
            
            GetMem2 ByVal pMethDesc + &H10, lFlags
            
            If lFlags And 2 Then
                
                GetMemPtr ByVal pMethDesc, pName
                GetMem2 ByVal pMethDesc + &H12, lMethOffset
                
                If lCount Then
                    If lCount > UBound(sRet) Then
                        ReDim Preserve sRet(lCount + 10)
                    End If
                Else
                    ReDim sRet(9)
                End If
                
                sRet(lCount) = SysAllocStringByteLen(ByVal pName, lstrlenA(ByVal pName))
                
                lCount = lCount + 1
                
            End If
            
        End If
        
        pMembers = pMembers + 4
        
    Next
    
    If lCount Then
        ReDim Preserve sRet(lCount - 1)
    End If
    
    ListOfMethods = sRet
    
End Property
Вложения
Тип файла: zip modVBInternals.zip (1,008 байт, 66 просмотров)
2
Модератор
10048 / 3894 / 883
Регистрация: 22.02.2013
Сообщений: 5,847
Записей в блоге: 79
04.02.2023, 12:50
Как определить что объект является пользовательским VB объектом?

Любой пользовательский объект поддерживает интерфейс AreYouABasicInstance (IID_AreYouABasicInstance = {0B6C9465-D082-11CF-8B4F-00A0C90F2704}). Для тех кто не любит библиотеки типов можно использовать следующий код:

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Option Explicit
 
Private Const AreYouABasicInstance  As String = "{0B6C9465-D082-11CF-8B4F-00A0C90F2704}"
 
Private Declare Function vbaCheckType Lib "msvbvm60" Alias "__vbaCheckType" (ByVal pObj As Any, ByRef pIID As Any) As Boolean
Private Declare Function IIDFromString Lib "ole32" (ByRef lpsz As Any, ByRef lpiid As Any) As Long
 
Private Sub Form_Load()
    Dim bIID(15)    As Byte
    
    IIDFromString ByVal StrPtr(AreYouABasicInstance), bIID(0)
 
    If vbaCheckType(Me, bIID(0)) Then
        MsgBox "VB obj"
    End If
    
End Sub
Вместо Me передается любой объект.

Добавлено через 10 минут
Перенаправление Debug.Print вывода в любой объект.

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
' //
' // Debug redirect
' // by The trick
' //
 
Option Explicit
 
Private Enum PTR
    [_]
End Enum
 
Private Declare Function GetModuleHandle Lib "kernel32" _
                         Alias "GetModuleHandleW" ( _
                         ByVal lpModuleName As PTR) As PTR
Private Declare Sub GetMem4 Lib "msvbvm60" ( _
                    ByRef pAddr As Any, _
                    ByRef pDst As Any)
Private Declare Sub GetMemPtr Lib "msvbvm60" _
                    Alias "GetMem4" ( _
                    ByRef pAddr As Any, _
                    ByRef pDst As Any)
Private Declare Sub GetMem8 Lib "msvbvm60" ( _
                    ByRef pAddr As Any, _
                    ByRef pDst As Any)
Private Declare Sub PutMemPtr Lib "msvbvm60" _
                    Alias "PutMem4" ( _
                    ByRef pDst As Any, _
                    ByVal pVal As PTR)
 
Private Function ReplaceDebugObject( _
                 ByVal pObj As PTR) As PTR
    Static s_pCurObject As PTR
    Dim hVBA        As PTR
    Dim pNTHdr      As PTR
    Dim pStart      As PTR
    Dim pEnd        As PTR
    Dim cSign       As Currency
    Dim lLength     As Long
    Dim lOldProtect As Long
    
    If s_pCurObject = 0 Then
    
        hVBA = GetModuleHandle(StrPtr("vba6"))
        If hVBA = 0 Then Exit Function
    
        GetMem4 ByVal hVBA + &H3C, pNTHdr
        pNTHdr = pNTHdr + hVBA
        
        GetMem4 ByVal pNTHdr + &H12C, pStart
        pStart = pStart + hVBA
        
        GetMem4 ByVal pNTHdr + &H128, lLength
        pEnd = pStart + lLength - 8
        
        Do While pStart <= pEnd
            
            GetMem8 ByVal pStart, cSign
            
            If cSign = 511398171365990.4051@ Then
            
                GetMemPtr ByVal pStart + &H11, pStart
                GetMemPtr ByVal pStart + &H44, pStart
                GetMemPtr ByVal pStart + &H1, s_pCurObject
                Exit Do
                
            End If
            
            pStart = pStart + 1
            
        Loop
 
    End If
    
    If s_pCurObject = 0 Then
        Err.Raise 51
    End If
    
    GetMemPtr ByVal s_pCurObject, ReplaceDebugObject
    PutMemPtr ByVal s_pCurObject, pObj
    
End Function
 
Private Sub Form_Load()
    Dim pOriginal   As PTR
    
    Me.AutoRedraw = True
    
    pOriginal = ReplaceDebugObject(ObjPtr(Me))
    
    Debug.Print "test"
    Debug.Print "Hello", "world", Spc(10); "1234"; Tab(3); "vb6"
 
    ReplaceDebugObject pOriginal
    
End Sub
Вместо ObjPtr(Me) можно передавать любой объект поддерживающий интерфейс IVBAPrint.

Добавлено через 42 минуты
CWaveFile - класс для работы с многоканальными WAVE-PCM файлами.

Данный класс позволяет создавать, открывать, сохранять многоканальные WAVE-PCM файлы. Можно отдельно проигрывать каналы и миксовать их.

https://github.com/thetrik/CWaveFile

Добавлено через 2 минуты
CSharedMemory - класс для динамического выделения памяти в расшаренной памяти.

https://github.com/thetrik/CSharedMemory
3
Модератор
10048 / 3894 / 883
Регистрация: 22.02.2013
Сообщений: 5,847
Записей в блоге: 79
04.02.2023, 13:15
Умножение 64 битных целых с индикацией переполнения.

Обычно когда мне нужно работать с 64 битными целыми числами я использую тип Currency. Для сложений и вычитаний можно использовать обычные + и -. Для умножения и деления можно использовать _allmul, _alldiv:

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Option Explicit
 
Private Declare Function allmul Lib "ntdll" _
                         Alias "_allmul" ( _
                         ByVal cMultiplicand As Currency, _
                         ByVal cMultiplier As Currency) As Currency
Private Declare Function alldiv Lib "ntdll" _
                         Alias "_alldiv" ( _
                         ByVal cDivident As Currency, _
                         ByVal cDivisor As Currency) As Currency
                         
Private Sub Form_Load()
    Debug.Print alldiv(5, 0.08) ' // 50000 / 800 = 62
    Debug.Print allmul(500, 8)  ' // 5000000 * 80000 = 400000000000
End Sub
Проблема функции _allmul в том что она не сигнализирует о переполнении, для этого я написал 2 функции mul64 и imul64 которые выполняют соответствующее умножение беззнаковых и знаковых 64 битных целы, а также сигнализируют о переполнении если результат не помещается в 64 битный результат. Функции реализованы в виде ассемблерной вставки, а вызываются через этот способ вызова функций по указателю. В архиве тест производительности данных функции и функции _allmul:



Сами функции:

Assembler
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
format PE GUI 4.0 DLL
 
entry EntryPoint
 
include 'win32wx.inc'
 
section '.code' code readable executable
 
proc EntryPoint hinstDLL,fdwReason,lpvReserved
        mov     eax,1
        ret
endp
 
mul64:
 
    mov eax, [esp + 0x10]       ; bh
 
    cmp dword [esp + 0x08], 0   ; ah
    je .no_ah
 
    test eax, eax
    jnz .set_overflow
 
    mov eax, [esp + 0x0c]       ; bl
    mul dword [esp + 0x08]      ; bl * ah
    jmp .continue
 
  .no_ah:
 
    test eax, eax
    jnz .has_bh
 
    mov eax, [esp + 0x04]       ; al
    mul dword [esp + 0x0c]      ; bl
    jmp .remove_overflow
 
  .has_bh:
 
    mul dword [esp + 0x04]      ; bh * al
 
  .continue:
 
    test edx, edx
    jnz .set_overflow
 
    mov ecx, eax
    mov eax, [esp + 0x04]   ; al
    mul dword [esp + 0x0c]  ; bl
    add edx, ecx
    jc .set_overflow
 
.remove_overflow:
    mov ecx, [esp + 0x14]
    mov [ecx], dword 0
    ret 0x14
 
.set_overflow:
    mov ecx, [esp + 0x14]
    mov [ecx], dword 1
    ret 0x14
 
imul64:
 
    push ebx
 
    xor ebx, ebx
 
    mov eax, [esp + 0x0c]       ; ah
    bt eax, 31
    jnc .check_b
 
    xor ecx, ecx
    neg dword [esp + 0x08]      ; - al
    sbb ecx, [esp + 0x0c]
    mov [esp + 0x0c], ecx
    inc ebx
 
  .check_b:
 
    mov eax, [esp + 0x14]       ; bh
    bt eax, 31
    jnc .mul_start
 
    xor ecx, ecx
    neg dword [esp + 0x10]      ; - bl
    sbb ecx, [esp + 0x14]
    mov [esp + 0x14], ecx
    inc ebx
 
    mov eax, ecx
 
  .mul_start:
 
    cmp dword [esp + 0x0c], 0   ; ah
    je .no_ah
 
    test eax, eax
    jnz .set_overflow
 
    mov eax, [esp + 0x10]       ; bl
    mul dword [esp + 0x0c]      ; bl * ah
    jmp .continue
 
  .no_ah:
 
    test eax, eax
    jnz .has_bh
 
    mov eax, [esp + 0x08]       ; al
    mul dword [esp + 0x10]      ; bl
    jmp .check_negate
 
  .has_bh:
 
    mul dword [esp + 0x08]      ; bh * al
 
  .continue:
 
    jc .set_overflow
 
    mov ecx, eax
    mov eax, [esp + 0x08]   ; al
    mul dword [esp + 0x10]  ; bl
    add edx, ecx
    jc .set_overflow
 
  .check_negate:
    jns .process_negate
 
    test eax, eax
    jnz .set_overflow
    cmp edx, 0x80000000
    jnz .set_overflow
 
    test bl, 1
    jnz .negate_result
    jmp .set_overflow
 
  .process_negate:
 
    test bl, 1
    jz .remove_overflow
 
  .negate_result:
 
    xor ecx, ecx
    xchg ecx, edx
    neg eax
    sbb edx, ecx
 
.remove_overflow:
    mov ecx, [esp + 0x18]
    mov [ecx], dword 0
    pop ebx
    ret 0x14
 
.set_overflow:
    mov ecx, [esp + 0x18]
    mov [ecx], dword 1
    pop ebx
    ret 0x14
 
section '.edata' export data readable
 
export 'mul64.dll', mul64, 'mul64', \
                    imul64, 'imul64'
 
section '.reloc' fixups data discardable
if $=$$
    dd 0,8
end if
Вложения
Тип файла: zip mul64VB.zip (3.2 Кб, 46 просмотров)
4
 Аватар для Mikle Quits
766 / 283 / 17
Регистрация: 21.01.2023
Сообщений: 436
08.02.2023, 11:08
Простой метроном на VB6.
В приложении простейший метроном, использующий DirectSound через .tlb от The trick
Это именно пример для понимания принципа, функций - минимум, зато просто.
Вложения
Тип файла: zip Metronome.zip (16.1 Кб, 65 просмотров)
2
Модератор
10048 / 3894 / 883
Регистрация: 22.02.2013
Сообщений: 5,847
Записей в блоге: 79
08.02.2023, 17:07
Простой секвенсор - драм-машина.

Используется этот класс для воспроизведения семплов.
Вложения
Тип файла: zip Sequencer.zip (600.2 Кб, 56 просмотров)
2
Модератор
10048 / 3894 / 883
Регистрация: 22.02.2013
Сообщений: 5,847
Записей в блоге: 79
10.02.2023, 20:58
Хеш-таблица со строковыми ключами.

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
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
' //
' // CHashTable.cls - hash table with string keys
' // The trick, 2023
' //
 
Option Explicit
Option Base 0
 
Private Const HASH_SIZE As Long = 587
 
Private Type tHashPointer
    lHash   As Long
    lIndex  As Long
End Type
 
Private Type tHashItem
    vValue      As Variant
    sKey        As String
    lNext       As Long
    lPrevEnum   As Long
    lNextEnum   As Long
End Type
 
Private Declare Function CharLowerBuff Lib "user32" _
                         Alias "CharLowerBuffW" ( _
                         ByVal lpsz As Long, _
                         ByVal cchLength As Long) As Long
Private Declare Sub HashData Lib "shlwapi" ( _
                    ByRef pbData As Any, _
                    ByVal cbData As Long, _
                    ByRef pbHash As Any, _
                    ByVal cbHash As Long)
 
Private m_tItems()          As tHashItem
Private m_bCaseInsensitive  As Boolean
Private m_lCount            As Long
Private m_lFirstFree        As Long
Private m_lFirstItem        As Long
Private m_lLastItem         As Long
 
Public Property Get CaseInsensitive() As Boolean
    CaseInsensitive = m_bCaseInsensitive
End Property
 
Public Property Let CaseInsensitive( _
                    ByVal bValue As Boolean)
    
    If m_lCount Then
        Err.Raise 5
    End If
    
    m_bCaseInsensitive = bValue
    
End Property
 
Public Function Exists( _
                ByRef sKey As String) As Boolean
    Exists = FindItem(sKey).lIndex <> -1
End Function
 
Public Property Get Item( _
                    ByRef sKey As String) As Variant
    Dim tPointer    As tHashPointer
    
    tPointer = FindItem(sKey)
    
    If tPointer.lIndex = -1 Then
        Item = Empty
    Else
        If IsObject(m_tItems(tPointer.lIndex).vValue) Then
            Set Item = m_tItems(tPointer.lIndex).vValue
        Else
             Item = m_tItems(tPointer.lIndex).vValue
        End If
    End If
 
End Property
 
Public Property Let Item( _
                    ByRef sKey As String, _
                    ByVal vValue As Variant)
    Dim tPointer    As tHashPointer
    
    tPointer = FindItem(sKey)
 
    If IsEmpty(vValue) Then
        If tPointer.lIndex = -1 Then
            Exit Property
        Else
            DeleteItem sKey
        End If
    Else
    
        If tPointer.lIndex = -1 Then
            tPointer = AddItem(sKey)
        End If
        
        m_tItems(tPointer.lIndex).vValue = vValue
        
    End If
    
End Property
 
Public Property Set Item( _
                    ByRef sKey As String, _
                    ByVal vValue As Variant)
    Dim tPointer    As tHashPointer
    
    tPointer = FindItem(sKey)
 
    If IsEmpty(vValue) Then
        If tPointer.lIndex = -1 Then
            Exit Property
        Else
            DeleteItem sKey
        End If
    Else
    
        If tPointer.lIndex = -1 Then
            tPointer = AddItem(sKey)
        End If
        
        Set m_tItems(tPointer.lIndex).vValue = vValue
        
    End If
    
End Property
 
Public Property Get Count() As Long
    Count = m_lCount
End Property
 
Public Sub Clear()
    Dim lIndex  As Long
    
    ReDim m_tItems(HASH_SIZE - 1)
    
    For lIndex = 0 To HASH_SIZE - 1
    
        m_tItems(lIndex).lNext = -1
        m_tItems(lIndex).lNextEnum = -1
        m_tItems(lIndex).lPrevEnum = -1
        
    Next
    
    m_lFirstFree = HASH_SIZE
    m_lFirstItem = -1
    m_lLastItem = -1
    m_lCount = 0
    
End Sub
 
Public Property Get Items() As Variant
    Dim lIndex      As Long
    Dim lItemIndex  As Long
    Dim vRet()      As Variant
    
    If m_lCount Then
        
        ReDim vRet(m_lCount - 1)
        
        lItemIndex = m_lFirstItem
        
        For lIndex = 0 To m_lCount - 1
        
            If IsObject(m_tItems(lItemIndex).vValue) Then
                Set vRet(lIndex) = m_tItems(lItemIndex).vValue
            Else
                vRet(lIndex) = m_tItems(lItemIndex).vValue
            End If
            
            lItemIndex = m_tItems(lItemIndex).lNextEnum
            
        Next
        
        Items = vRet
        
    Else
        Items = Split("")
    End If
    
End Property
 
Public Property Get Keys() As String()
    Dim lIndex      As Long
    Dim lItemIndex  As Long
    Dim sRet()      As String
    
    If m_lCount Then
        
        ReDim sRet(m_lCount - 1)
        
        lItemIndex = m_lFirstItem
        
        For lIndex = 0 To m_lCount - 1
        
            sRet(lIndex) = m_tItems(lItemIndex).sKey
            lItemIndex = m_tItems(lItemIndex).lNextEnum
            
        Next
    
    End If
    
    Keys = sRet
    
End Property
 
Public Function CalculateHash( _
                ByVal sKey As String) As Long
    Dim lHash   As Long
    
    If m_bCaseInsensitive Then
        CharLowerBuff StrPtr(sKey), Len(sKey)
    End If
    
    HashData ByVal StrPtr(sKey), LenB(sKey), lHash, Len(lHash)
    
    CalculateHash = (lHash And &H7FFFFFFF) Mod HASH_SIZE
    
End Function
 
Private Sub DeleteItem( _
            ByRef sKey As String)
    Dim lHash       As Long
    Dim lIndex      As Long
    Dim lNextIndex  As Long
    Dim lPrevIndex  As Long
    Dim eComp       As VbCompareMethod
    
    lHash = CalculateHash(sKey)
    
    If m_bCaseInsensitive Then
        eComp = vbTextCompare
    Else
        eComp = vbBinaryCompare
    End If
    
    lIndex = lHash
    lPrevIndex = -1
    
    Do While StrComp(sKey, m_tItems(lIndex).sKey, eComp)
    
        lPrevIndex = lIndex
        lIndex = m_tItems(lIndex).lNext
        If lIndex = -1 Then Exit Sub    ' // Not found
        
    Loop
 
    If lPrevIndex = -1 Then
        
        ' // In main hash table
        lNextIndex = m_tItems(lIndex).lNext
 
        If lNextIndex <> -1 Then
            
            ' // Move next collision to main table
            m_tItems(lIndex).sKey = m_tItems(lNextIndex).sKey
            
            If IsObject(m_tItems(lNextIndex).vValue) Then
                Set m_tItems(lIndex).vValue = m_tItems(lNextIndex).vValue
            Else
                m_tItems(lIndex).vValue = m_tItems(lNextIndex).vValue
            End If
            
            If m_tItems(lIndex).lPrevEnum <> -1 Then
                m_tItems(m_tItems(lIndex).lPrevEnum).lNextEnum = m_tItems(lIndex).lNextEnum
            End If
            
            If m_tItems(lIndex).lNextEnum <> -1 Then
                m_tItems(m_tItems(lIndex).lNextEnum).lPrevEnum = m_tItems(lIndex).lPrevEnum
            End If
            
            If m_tItems(lNextIndex).lPrevEnum <> -1 Then
                m_tItems(m_tItems(lNextIndex).lPrevEnum).lNextEnum = lIndex
            End If
            
            If m_tItems(lNextIndex).lNextEnum <> -1 Then
                m_tItems(m_tItems(lNextIndex).lNextEnum).lPrevEnum = lIndex
            End If
            
            If m_lFirstItem = lNextIndex Then
                m_lFirstItem = lIndex
            ElseIf m_lFirstItem = lIndex Then
                If m_tItems(lIndex).lNextEnum <> lNextIndex Then
                    m_lFirstItem = m_tItems(lIndex).lNextEnum
                End If
            End If
            
            If m_lLastItem = lNextIndex Then
                m_lLastItem = lIndex
            ElseIf m_lLastItem = lIndex Then
                If m_tItems(lIndex).lPrevEnum <> lNextIndex Then
                    m_lLastItem = m_tItems(lIndex).lPrevEnum
                End If
            End If
            
            m_tItems(lIndex).lNextEnum = m_tItems(lNextIndex).lNextEnum
            m_tItems(lIndex).lPrevEnum = m_tItems(lNextIndex).lPrevEnum
            m_tItems(lIndex).lNext = m_tItems(lNextIndex).lNext
            
            DeallocItem lNextIndex
            
        Else
            
            If m_lFirstItem = lIndex Then
                m_lFirstItem = m_tItems(lIndex).lNextEnum
            End If
            
            If m_lLastItem = lIndex Then
                m_lLastItem = m_tItems(lIndex).lPrevEnum
            End If
            
            If m_tItems(lIndex).lNextEnum <> -1 Then
                m_tItems(m_tItems(lIndex).lNextEnum).lPrevEnum = m_tItems(lIndex).lPrevEnum
            End If
            
            If m_tItems(lIndex).lPrevEnum <> -1 Then
                m_tItems(m_tItems(lIndex).lPrevEnum).lNextEnum = m_tItems(lIndex).lNextEnum
            End If
 
            m_tItems(lIndex).sKey = vbNullString
            m_tItems(lIndex).vValue = Empty
            m_tItems(lIndex).lNext = -1
            m_tItems(lIndex).lNextEnum = -1
            m_tItems(lIndex).lPrevEnum = -1
            
        End If
 
    Else
        
        m_tItems(lPrevIndex).lNext = m_tItems(lIndex).lNext
        
        If m_lFirstItem = lIndex Then
            m_lFirstItem = m_tItems(lIndex).lNextEnum
        End If
        
        If m_lLastItem = lIndex Then
            m_lLastItem = m_tItems(lIndex).lPrevEnum
        End If
            
        If m_tItems(lIndex).lNextEnum <> -1 Then
            m_tItems(m_tItems(lIndex).lNextEnum).lPrevEnum = m_tItems(lIndex).lPrevEnum
        End If
        
        If m_tItems(lIndex).lPrevEnum <> -1 Then
            m_tItems(m_tItems(lIndex).lPrevEnum).lNextEnum = m_tItems(lIndex).lNextEnum
        End If
        
        DeallocItem lIndex
        
    End If
    
    m_lCount = m_lCount - 1
    
End Sub
 
Private Function AddItem( _
                 ByRef sKey As String) As tHashPointer
    Dim lIndex      As Long
    Dim lNewIndex   As Long
    Dim eComp       As VbCompareMethod
    
    If m_bCaseInsensitive Then
        eComp = vbTextCompare
    Else
        eComp = vbBinaryCompare
    End If
    
    lIndex = CalculateHash(sKey)
    
    AddItem.lHash = lIndex
    
    Do While StrComp(sKey, m_tItems(lIndex).sKey, eComp)
        If m_tItems(lIndex).lNext = -1 Then
            
            If lIndex = AddItem.lHash And Len(m_tItems(lIndex).sKey) = 0 Then
                lNewIndex = lIndex
            Else
                lNewIndex = AllocItem
                m_tItems(lIndex).lNext = lNewIndex
            End If
            
            m_tItems(lNewIndex).sKey = sKey
            m_tItems(lNewIndex).lNext = -1
            m_tItems(lNewIndex).lNextEnum = -1
            
            If m_lFirstItem = -1 Then
                m_lFirstItem = lNewIndex
            End If
            
            m_tItems(lNewIndex).lPrevEnum = m_lLastItem
            
            If m_lLastItem <> -1 Then
                m_tItems(m_lLastItem).lNextEnum = lNewIndex
            End If
            
            m_lLastItem = lNewIndex
            
            lIndex = lNewIndex
            
            m_lCount = m_lCount + 1
            
            Exit Do
            
        Else
            lIndex = m_tItems(lIndex).lNext
        End If
    Loop
    
    AddItem.lIndex = lIndex
    
End Function
 
Private Function FindItem( _
                 ByRef sKey As String) As tHashPointer
    Dim lIndex  As Long
    Dim eComp   As VbCompareMethod
    
    If m_bCaseInsensitive Then
        eComp = vbTextCompare
    Else
        eComp = vbBinaryCompare
    End If
    
    lIndex = CalculateHash(sKey)
    
    FindItem.lHash = lIndex
    
    Do While StrComp(sKey, m_tItems(lIndex).sKey, eComp)
        lIndex = m_tItems(lIndex).lNext
        If lIndex = -1 Then Exit Do
    Loop
    
    FindItem.lIndex = lIndex
    
End Function
 
Private Sub DeallocItem( _
            ByVal lIndex As Long)
                
    m_tItems(lIndex).sKey = vbNullString
    m_tItems(lIndex).vValue = Empty
    m_tItems(lIndex).lNext = m_lFirstFree
    m_tItems(lIndex).lNextEnum = -1
    m_tItems(lIndex).lPrevEnum = -1
    
    m_lFirstFree = lIndex
                
End Sub
 
Private Function AllocItem() As Long
    Dim lIndex      As Long
    Dim lCurSize    As Long
    
    If m_lFirstFree > UBound(m_tItems) Then
        
        lCurSize = (UBound(m_tItems) + 1)
        ReDim Preserve m_tItems(lCurSize * 2 - 1)
        
        For lIndex = lCurSize To UBound(m_tItems)
        
            m_tItems(lIndex).lNext = lIndex + 1
            m_tItems(lIndex).lNextEnum = -1
            m_tItems(lIndex).lPrevEnum = -1
            
        Next
        
    End If
    
    AllocItem = m_lFirstFree
    m_lFirstFree = m_tItems(m_lFirstFree).lNext
    
End Function
 
Private Sub Class_Initialize()
 
    Clear
    m_bCaseInsensitive = True
    
End Sub
2
Модератор
10048 / 3894 / 883
Регистрация: 22.02.2013
Сообщений: 5,847
Записей в блоге: 79
11.02.2023, 11:25
Получить стек вызовов в строковую переменную.

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
' //
' // Get calling procedure name
' // The result executable should be compiled with debug symbols
' // by The trick 2022
' //
 
Option Explicit
Option Base 0
 
Private Enum PTR    ' // Alias (thanks OlimilO1402)
    [_]
End Enum
 
Private Const MAX_SYM_NAME                                  As Long = 2000
Private Const MAX_PATH                                      As Long = 260
Private Const SIZEOF_SYMBOL_INFO                            As Long = 88
Private Const GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS        As Long = 4
Private Const GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT  As Long = 2
 
Private Type SYMBOL_INFO
    SizeOfStruct            As Long
    TypeIndex               As Long
    Reserved(1)             As Currency
    Index                   As Long
    Size                    As Long
    ModBase                 As Currency
    Flags                   As Long
    lPad0                   As Long
    Value                   As Currency
    Address                 As Currency
    Register                As Long
    Scope                   As Long
    Tag                     As Long
    NameLen                 As Long
    MaxNameLen              As Long
    iName(MAX_SYM_NAME - 1) As Integer
End Type
 
Private Declare Function SymInitialize Lib "dbghelp" _
                         Alias "SymInitializeW" ( _
                         ByVal hProcess As OLE_HANDLE, _
                         ByVal UserSearchPath As Any, _
                         ByVal fInvadeProcess As Long) As Long
Private Declare Function SymFromAddr Lib "dbghelp" _
                         Alias "SymFromAddrW" ( _
                         ByVal hProcess As OLE_HANDLE, _
                         ByVal Address As Currency, _
                         ByRef Displacement As Currency, _
                         ByRef Symbol As SYMBOL_INFO) As Long
Private Declare Function SymLoadModuleEx Lib "dbghelp" _
                         Alias "SymLoadModuleExW" ( _
                         ByVal hProcess As OLE_HANDLE, _
                         ByVal hFile As OLE_HANDLE, _
                         ByVal ImageName As PTR, _
                         ByVal ModuleName As PTR, _
                         ByVal BaseOfDll As Currency, _
                         ByVal DllSize As Long, _
                         ByRef Data As Any, _
                         ByVal Flags As Long) As Long
Private Declare Function GetModuleFileName Lib "kernel32" _
                         Alias "GetModuleFileNameW" ( _
                         ByVal hModule As Long, _
                         ByVal lpFileName As PTR, _
                         ByVal nSize As Long) As Long
Private Declare Function GetModuleHandleEx Lib "kernel32" _
                         Alias "GetModuleHandleExW" ( _
                         ByVal dwFlags As Long, _
                         ByVal lpModuleName As PTR, _
                         ByRef phModule As Any) As Long
Private Declare Function SysAllocString Lib "oleaut32" ( _
                         ByRef pOlechar As Any) As Long
Private Declare Function EbSetMode Lib "vba6" ( _
                         ByVal Mode As Long) As Long
Private Declare Function EbGetCallstackCount Lib "vba6" ( _
                         ByRef lCount As Long) As Long
Private Declare Function EbGetCallstackFunction Lib "vba6" ( _
                         ByVal lIndex As Long, _
                         ByVal pProject As PTR, _
                         ByVal pModule As PTR, _
                         ByVal pFunction As PTR, _
                         ByRef lRet As Long) As Long
Private Declare Function RtlCaptureStackBackTrace Lib "kernel32" ( _
                         ByVal FramesToSkip As Long, _
                         ByVal FramesToCapture As Long, _
                         ByRef BackTrace As Any, _
                         ByRef BackTraceHash As Any) As Integer
Private Declare Sub GetMem4 Lib "msvbvm60" ( _
                    ByRef pAddr As Any, _
                    ByRef pRetVal As Any)
Private Declare Sub PutMemPtr Lib "msvbvm60" _
                    Alias "PutMem4" ( _
                    ByRef pAddr As Any, _
                    ByVal pNewVal As PTR)
 
Private m_bInintialized As Boolean
 
Public Function GetCallStack() As String
    Dim tSymInfo    As SYMBOL_INFO
    Dim cAddr       As Currency
    Dim cDisp       As Currency
    Dim bIsInIDE    As Boolean
    Dim lStackCount As Long
    Dim sProject    As String
    Dim sModule     As String
    Dim sFunction   As String
    Dim lIndex      As Long
    Dim pAddr()     As PTR
    
    Debug.Assert MakeTrue(bIsInIDE)
    
    If bIsInIDE Then
        
        EbSetMode 2
        
        If EbGetCallstackCount(lStackCount) >= 0 Then
            For lIndex = 1 To lStackCount - 1
                If EbGetCallstackFunction(lIndex, VarPtr(sProject), VarPtr(sModule), VarPtr(sFunction), 0) >= 0 Then
                
                    GetCallStack = GetCallStack & sModule & "::" & sFunction & vbNewLine
                    sProject = vbNullString
                    sModule = vbNullString
                    sFunction = vbNullString
                    
                End If
            Next
        End If
        
        EbSetMode 1
        
        Exit Function
        
    End If
    
    If Not m_bInintialized Then
        If SymInitialize(VarPtr(m_bInintialized), ByVal 0&, 0) = 0 Then
            Exit Function
        ElseIf SymLoadModuleEx(VarPtr(m_bInintialized), 0, StrPtr(GetExecutableName), 0, 0@, 0, ByVal 0&, 0) = 0 Then
            Exit Function
        Else
            m_bInintialized = True
        End If
    End If
    
    tSymInfo.SizeOfStruct = SIZEOF_SYMBOL_INFO
    tSymInfo.MaxNameLen = MAX_SYM_NAME
    
    ReDim pAddr(31)
    
    lStackCount = RtlCaptureStackBackTrace(1, UBound(pAddr) + 1, pAddr(0), ByVal 0&)
    
    For lIndex = 0 To UBound(pAddr)
    
        GetMem4 pAddr(lIndex), cAddr
    
        If SymFromAddr(VarPtr(m_bInintialized), cAddr, cDisp, tSymInfo) Then
            
            PutMemPtr ByVal VarPtr(sFunction), SysAllocString(tSymInfo.iName(0))
            GetCallStack = GetCallStack & sFunction & vbNewLine
            sFunction = vbNullString
            
        Else
            
            GetCallStack = GetCallStack & "<unknown>" & vbNewLine
            
        End If
 
    Next
    
End Function
 
Public Function GetCallingProcName( _
                Optional ByVal lReserved As Long) As String
    Dim tSymInfo    As SYMBOL_INFO
    Dim cAddr       As Currency
    Dim cDisp       As Currency
    Dim bIsInIDE    As Boolean
    Dim lStackCount As Long
    Dim sProject    As String
    Dim sModule     As String
    Dim sFunction   As String
    
    Debug.Assert MakeTrue(bIsInIDE)
    
    If bIsInIDE Then
        
        EbSetMode 2
        
        If EbGetCallstackCount(lStackCount) >= 0 Then
            If lStackCount > 1 Then
                If EbGetCallstackFunction(1, VarPtr(sProject), VarPtr(sModule), VarPtr(sFunction), 0) >= 0 Then
                    GetCallingProcName = sModule & "::" & sFunction
                End If
            End If
        End If
        
        EbSetMode 1
        
        Exit Function
        
    End If
    
    If Not m_bInintialized Then
        If SymInitialize(VarPtr(m_bInintialized), ByVal 0&, 0) = 0 Then
            Exit Function
        ElseIf SymLoadModuleEx(VarPtr(m_bInintialized), 0, StrPtr(GetExecutableName), 0, 0@, 0, ByVal 0&, 0) = 0 Then
            Exit Function
        Else
            m_bInintialized = True
        End If
    End If
    
    tSymInfo.SizeOfStruct = SIZEOF_SYMBOL_INFO
    tSymInfo.MaxNameLen = MAX_SYM_NAME
    
    GetMem4 ByVal VarPtr(lReserved) - 4, cAddr
    
    If SymFromAddr(VarPtr(m_bInintialized), cAddr, cDisp, tSymInfo) = 0 Then
        Exit Function
    End If
    
    PutMemPtr ByVal VarPtr(GetCallingProcName), SysAllocString(tSymInfo.iName(0))
    
End Function
 
Private Function MakeTrue( _
                 ByRef bValue As Boolean) As Boolean
    MakeTrue = True
    bValue = True
End Function
 
Private Function GetExecutableName() As String
    Dim sRet    As String
    Dim lSize   As Long
    Dim hMod    As PTR
    
    If GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS Or GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, _
                         AddressOf GetCallingProcName, hMod) = 0 Then
        Exit Function
    End If
    
    sRet = Space$(MAX_PATH)
    lSize = GetModuleFileName(hMod, StrPtr(sRet), Len(sRet))
    
    If lSize Then
        GetExecutableName = Left$(sRet, lSize)
    End If
 
End Function
В аттаче пример. Скомпилированный вариант должен быть с отладочными символами.
Вложения
Тип файла: zip DbgHelp.zip (15.1 Кб, 49 просмотров)
2
Испарился
 Аватар для HackerVlad
1741 / 637 / 45
Регистрация: 10.09.2021
Сообщений: 2,769
15.02.2023, 18:51
Полезная программа ClipboardPath исправляющая неверную кодировку русского текста в буфере обмена

Представляю Вашему вниманию супер заплатку для винды, программу которая сама автоматически исправляет буфер обмена Windows, если в нём содержится неверный русский текст (кракозяблики или вопросительные знаки вместо русских букв). Такой программы в Интернете больше нигде нет. Я её написал чтобы сэкономить кучу нервов при копировании русского текста в буфера, в английской раскладке клавиатуры. Актуальна для Win 7 и выше, потому как в XP у меня такой проблемы нет вообще (проверял).

Теперь есть ответ на вопрос как решить проблему корректной вставки русского текста из буфера обмена Windows!!! Не понимаю только почему люди раньше не написали эту программу или разработчики Punto Switcher'а не сделали такую функцию...

Я её написал всего за один день! На второй день немного доработал, довёл до ума, добавил даже звук при авто-исправлении буфера, Вы сами можете проверить как она работает, если нажимать Ctrl+C в тексте и копировать в английской раскладке то будет исправляться буфер и будет проигрываться специальный звук (WAV-файл), а если копировать в русской раскладке то ничего происходить не будет! Вавку убрать легко, если это будет напрягать.

Хоть программа и основана на работе таймера каждую секунду, она не сильно нагружает процессор, я проверял через программу Process Hacker. При больших объёмах информации внутри буфера нагрузка ЦП всего 0.1. При любом маленьком тексте в буфере так вообще никакой нагрузки на процессор.

Так что радуйтесь!!! Ваша мечта сбылась!!! Теперь никогда не будет проблем при копировании русского текста в английской раскладке)))))

Хоть продавай эту программу))) Вообще суперская))) Я конечно бесплатно для всех выкладываю))))

Для тех кто не хочет качать зипку, вот код:
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
Option Explicit
 
Private Declare Function OpenClipboard Lib "user32.dll" (ByVal hwnd As Long) As Long
Private Declare Function GetClipboardData Lib "user32.dll" (ByVal wFormat As Long) As Long
Private Declare Function SetClipboardData Lib "user32.dll" (ByVal wFormat As Long, ByVal hMem As Long) As Long
Private Declare Function CloseClipboard Lib "user32.dll" () As Long
Private Declare Function GlobalAlloc Lib "kernel32.dll" (ByVal wFlags As Long, ByVal dwBytes As Long) As Long
Private Declare Function lstrcpyn Lib "kernel32.dll" Alias "lstrcpynW" (ByVal lpString1 As Long, ByVal lpString2 As Long, ByVal iMaxLength As Long) As Long
Private Declare Function GlobalLock Lib "kernel32.dll" (ByVal hMem As Long) As Long
Private Declare Function GlobalUnlock Lib "kernel32.dll" (ByVal hMem As Long) As Long
Private Declare Function GlobalSize Lib "kernel32.dll" (ByVal hMem As Long) As Long
Private Declare Function GetMem4 Lib "msvbvm60.dll" (src As Any, dst As Any) As Long
Private Declare Sub ZeroMemory Lib "kernel32.dll" Alias "RtlZeroMemory" (Destination As Any, ByVal Length As Long)
Private Declare Function sndPlaySound Lib "winmm.dll" Alias "sndPlaySoundA" (ByVal lpszSoundName As String, ByVal uFlags As Long) As Long
 
Private Const CF_UNICODETEXT    As Long = 13&
Private Const CF_LOCALE         As Long = 16
Private Const GMEM_MOVEABLE     As Long = &H2&
Private Const SND_ASYNC = &H1
Private Const SND_NODEFAULT = &H2
 
Dim LenClipboardA As Long
Dim LenClipboardW As Long
Dim EffortClipboardA As String
Dim EffortClipboardW As String
 
Private Function wAppPath() As String
    If Right$(App.Path, 1) = "\" Then
        wAppPath = Mid(App.Path, 1, Len(App.Path) - 1)
    Else
        wAppPath = App.Path
    End If
End Function
 
' Получить буфер в уникоде
Private Function GetClipboardW() As String
    On Error GoTo ErrorHandler
    
    Dim hMem As Long
    Dim ptr  As Long
    Dim Size As Long
    Dim txt  As String
    
    If OpenClipboard(0) Then
        hMem = GetClipboardData(CF_UNICODETEXT)
        If hMem Then
            Size = GlobalSize(hMem)
            If Size Then
                txt = Space$(Size \ 2 - 1)
                ptr = GlobalLock(hMem)
                lstrcpyn ByVal StrPtr(txt), ByVal ptr, Size
                GlobalUnlock hMem
                GetClipboardW = txt
            End If
        End If
        CloseClipboard
    End If
    Exit Function
ErrorHandler:
    'Debug.Print "GetClipboardW" & " - #" & Err.Number & " " & Err.Description & ". LastDllError = " & Err.LastDllError
End Function
 
' Записать уникодную строку в буфер
Private Sub SetClipboardW(sText As String)
    On Error GoTo ErrorHandler
    Dim hMem As Long
    Dim ptr  As Long
    Dim Size As Long
    Dim txt  As String
    
    If OpenClipboard(0) Then
        hMem = GlobalAlloc(GMEM_MOVEABLE, 4)
        If hMem <> 0 Then
            ptr = GlobalLock(hMem)
            If ptr <> 0 Then
                GetMem4 &H419, ByVal ptr
                GlobalUnlock hMem
                SetClipboardData CF_LOCALE, hMem
            End If
            'GlobalFree hMem 'do not free!!!
        End If
        hMem = GlobalAlloc(GMEM_MOVEABLE, LenB(sText) + 2)
        If hMem <> 0 Then
            ptr = GlobalLock(hMem)
            If ptr <> 0 Then
                lstrcpyn ptr, StrPtr(sText), LenB(sText)
                ZeroMemory ByVal (StrPtr(sText) + LenB(sText)), 2&
                GlobalUnlock hMem
                SetClipboardData CF_UNICODETEXT, hMem
            End If
            'GlobalFree hMem 'do not free!!!
        End If
        CloseClipboard
    End If
    Exit Sub
ErrorHandler:
    'Debug.Print "SetClipboardW" & " - #" & Err.Number & " " & Err.Description & ". LastDllError = " & Err.LastDllError
End Sub
 
' Возьмём символы а-я, А-Я, ёЁ с кодами от 192 до 255 а так же 184 и 168
' Определить содержит ли буфер CF_UNICODETEXT кракозяблики символы а-я, А-Я, ёЁ
Private Function IsCrabsString(str As String) As Boolean
    Dim i As Integer
    
    For i = 192 To 255
        If InStr(1, str, ChrW(i)) > 0 Then
            IsCrabsString = True
            Exit Function ' Для ускорения
        End If
    Next
    
    If InStr(1, str, ChrW(184)) > 0 Then IsCrabsString = True
    If InStr(1, str, ChrW(168)) > 0 Then IsCrabsString = True
End Function
 
Private Function IsQuestionString(str As String) As Boolean
    str = Replace(str, " ", "")
    
    If str = "?" Or str = "??" Or str = "???" Or str = "????" Or str = "?????" Then
        IsQuestionString = True
        Exit Function ' Для ускорения
    End If
    If Len(str) > 5 Then ' Если 6 вопросительных знаков вподряд и более
        If Mid(str, 1, 6) = "??????" Then
            IsQuestionString = True
            Exit Function ' Для ускорения
        End If
    End If
    If InStr(1, str, "?????") Then
        IsQuestionString = True
    End If
End Function
 
Private Sub ClipboardPath()
    On Error Resume Next
    
    Dim ClipboardA As String
    Dim ClipboardW As String
    
    ClipboardA = Clipboard.GetText
    ClipboardW = GetClipboardW
    
    If LenClipboardW <> Len(ClipboardW) Then ' Выполнять код, только если буфер изменился
        LenClipboardW = Len(ClipboardW)
                
        If Len(ClipboardW) > 0 Then
            If IsCrabsString(ClipboardW) = True Then ' Буфер содержит кракозяблики
                SetClipboardW ClipboardA ' Исправить буфер (засунуть в CF_UNICODETEXT правильную строку взятую из CF_TEXT)
                sndPlaySound wAppPath & "\FixingClipboard.wav", SND_ASYNC Or SND_NODEFAULT
                EffortClipboardW = Mid(ClipboardA, 1, 8)
                Exit Sub ' Для ускорения
            End If
        End If
    Else ' Если количество символов всё-таки одинаковое
        If Len(ClipboardW) > 0 And LenClipboardW > 0 Then
            LenClipboardW = Len(ClipboardW)
            
            If EffortClipboardW <> vbNullString Then
                If Mid(ClipboardW, 1, 8) <> EffortClipboardW Then ' Выполнять код, только если реально буфер изменился
                    If IsCrabsString(ClipboardW) = True Then ' Буфер содержит кракозяблики
                        SetClipboardW ClipboardA ' Исправить буфер (засунуть в CF_UNICODETEXT правильную строку взятую из CF_TEXT)
                        sndPlaySound wAppPath & "\FixingClipboard.wav", SND_ASYNC Or SND_NODEFAULT
                        EffortClipboardW = Mid(ClipboardA, 1, 8)
                        Exit Sub ' Для ускорения
                    End If
                End If
            End If
        End If
    End If
    
    If LenClipboardA <> Len(ClipboardA) Then ' Выполнять код, только если буфер изменился
        LenClipboardA = Len(ClipboardA)
        
        If Len(ClipboardA) > 0 Then
            If IsQuestionString(ClipboardA) = True Then
                Clipboard.SetText ClipboardW ' Исправить буфер (засунуть в CF_TEXT правильную строку взятую из CF_UNICODETEXT)
                sndPlaySound wAppPath & "\FixingClipboard.wav", SND_ASYNC Or SND_NODEFAULT
                EffortClipboardA = Mid(ClipboardW, 1, 8)
            End If
        End If
    Else ' Если количество символов всё-таки одинаковое
        If Len(ClipboardA) > 0 And LenClipboardA > 0 Then
            LenClipboardA = Len(ClipboardA)
            
            If EffortClipboardA <> vbNullString Then
                If Mid(ClipboardA, 1, 8) <> EffortClipboardA Then ' Выполнять код, только если реально буфер изменился
                    If IsQuestionString(ClipboardA) = True Then
                        Clipboard.SetText ClipboardW ' Исправить буфер (засунуть в CF_TEXT правильную строку взятую из CF_UNICODETEXT)
                        sndPlaySound wAppPath & "\FixingClipboard.wav", SND_ASYNC Or SND_NODEFAULT
                        EffortClipboardA = Mid(ClipboardW, 1, 8)
                    End If
                End If
            End If
        End If
    End If
End Sub
 
Private Sub Form_Load()
    Me.Hide
    App.TaskVisible = False
    
    If App.PrevInstance = True Then
        Unload Me
        End
    End If
End Sub
 
Private Sub Timer1_Timer()
    ClipboardPath
End Sub
Вложения
Тип файла: zip ClipboardPath.zip (14.6 Кб, 56 просмотров)
4
Испарился
 Аватар для HackerVlad
1741 / 637 / 45
Регистрация: 10.09.2021
Сообщений: 2,769
20.02.2023, 01:55
ClipboardPath версия 2.0 значительно улучшенная версия

Прежде всего хочу выразить огромную благодарность Dragokas за написание технологии субклассирования и отлова событий буфера, а так же за помощь в разработке функций. Таким образом смог полностью отказаться от таймера. Так же спасибо ещё и The trick за хорошие советы.

Теперь программа работает идеально и совершенно не нагружает процессор. В предыдущей версии, к сожалению, при копировании гигантских данных очень сильно нагружался процессор до 100% на много секунд. Теперь всё стало работать очень быстро. Благодаря быстрым функциям и улучшениям. Так же были исправлены мелкие баги, такие как неправильное поведение при копировании китайщины.

Теперь наслаждайтесь и пользуйтесь! Ваш буфер обмена будет всегда с правильным русским текстом!!!

Код формы...
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
Option Explicit
 
Private Declare Function OpenClipboard Lib "user32.dll" (ByVal hwnd As Long) As Long
Private Declare Function GetClipboardData Lib "user32.dll" (ByVal wFormat As Long) As Long
Private Declare Function SetClipboardData Lib "user32.dll" (ByVal wFormat As Long, ByVal hMem As Long) As Long
Private Declare Function CloseClipboard Lib "user32.dll" () As Long
Private Declare Function GlobalAlloc Lib "kernel32.dll" (ByVal wFlags As Long, ByVal dwBytes As Long) As Long
Private Declare Function lstrcpyn Lib "kernel32.dll" Alias "lstrcpynW" (ByVal lpString1 As Long, ByVal lpString2 As Long, ByVal iMaxLength As Long) As Long
Private Declare Function GlobalLock Lib "kernel32.dll" (ByVal hMem As Long) As Long
Private Declare Function GlobalUnlock Lib "kernel32.dll" (ByVal hMem As Long) As Long
Private Declare Function GlobalSize Lib "kernel32.dll" (ByVal hMem As Long) As Long
Private Declare Function GetMem4 Lib "msvbvm60.dll" (src As Any, dst As Any) As Long
Private Declare Sub ZeroMemory Lib "kernel32.dll" Alias "RtlZeroMemory" (Destination As Any, ByVal Length As Long)
Private Declare Function sndPlaySound Lib "winmm.dll" Alias "sndPlaySoundA" (ByVal lpszSoundName As String, ByVal uFlags As Long) As Long
 
Private Const CF_UNICODETEXT    As Long = 13&
Private Const CF_LOCALE         As Long = 16
Private Const GMEM_MOVEABLE     As Long = &H2&
Private Const SND_ASYNC = &H1
Private Const SND_NODEFAULT = &H2
 
Private Function wAppPath() As String
    If Right$(App.Path, 1) = "\" Then
        wAppPath = Mid(App.Path, 1, Len(App.Path) - 1)
    Else
        wAppPath = App.Path
    End If
End Function
 
' Получить буфер в уникоде
Private Function GetClipboardW() As String
    On Error GoTo ErrorHandler
    
    Dim hMem As Long
    Dim ptr  As Long
    Dim Size As Long
    Dim txt  As String
    
    If OpenClipboard(0) Then
        hMem = GetClipboardData(CF_UNICODETEXT)
        If hMem Then
            Size = GlobalSize(hMem)
            If Size Then
                txt = Space$(Size \ 2 - 1)
                ptr = GlobalLock(hMem)
                lstrcpyn ByVal StrPtr(txt), ByVal ptr, Size
                GlobalUnlock hMem
                GetClipboardW = txt
            End If
        End If
        CloseClipboard
    End If
    Exit Function
ErrorHandler:
    'Debug.Print "GetClipboardW" & " - #" & Err.Number & " " & Err.Description & ". LastDllError = " & Err.LastDllError
End Function
 
' Записать уникодную строку в буфер
Private Sub SetClipboardW(sText As String)
    On Error GoTo ErrorHandler
    Dim hMem As Long
    Dim ptr  As Long
    Dim Size As Long
    Dim txt  As String
    
    If OpenClipboard(0) Then
        hMem = GlobalAlloc(GMEM_MOVEABLE, 4)
        If hMem <> 0 Then
            ptr = GlobalLock(hMem)
            If ptr <> 0 Then
                GetMem4 &H419, ByVal ptr
                GlobalUnlock hMem
                SetClipboardData CF_LOCALE, hMem
            End If
            'GlobalFree hMem 'do not free!!!
        End If
        hMem = GlobalAlloc(GMEM_MOVEABLE, LenB(sText) + 2)
        If hMem <> 0 Then
            ptr = GlobalLock(hMem)
            If ptr <> 0 Then
                lstrcpyn ptr, StrPtr(sText), LenB(sText)
                ZeroMemory ByVal (StrPtr(sText) + LenB(sText)), 2&
                GlobalUnlock hMem
                SetClipboardData CF_UNICODETEXT, hMem
            End If
            'GlobalFree hMem 'do not free!!!
        End If
        CloseClipboard
    End If
    Exit Sub
ErrorHandler:
    'Debug.Print "SetClipboardW" & " - #" & Err.Number & " " & Err.Description & ". LastDllError = " & Err.LastDllError
End Sub
 
Private Function IsQuestionString(str As String) As Boolean
    If str = "?" Or str = "??" Or str = "???" Or str = "????" Or str = "?????" Or str = "??????" Then
        IsQuestionString = True
        Exit Function ' Для ускорения
    End If
    
    If str Like "*[?]*" Then ' Если найден знак вопроса
        If Len(str) < 32768 Then
            str = Replace(str, " ", "")
            str = Replace(str, ",", "")
            str = Replace(str, ".", "")
        End If
        
        If InStr(1, str, "?????") Then
            IsQuestionString = True
            Exit Function ' Для ускорения
        End If
        
        If InStr(1, str, "? ????") Then
            IsQuestionString = True
            Exit Function ' Для ускорения
        End If
        If InStr(1, str, "?? ???") Then
            IsQuestionString = True
            Exit Function ' Для ускорения
        End If
        If InStr(1, str, "??? ??") Then
            IsQuestionString = True
            Exit Function ' Для ускорения
        End If
        If InStr(1, str, "???? ?") Then
            IsQuestionString = True
        End If
    End If
End Function
 
Private Sub ClipboardPath()
    On Error Resume Next
    
    Dim ClipboardA As String
    Dim ClipboardW As String
    
    ClipboardA = Clipboard.GetText
    ClipboardW = GetClipboardW
    
    If Len(ClipboardW) > 0 Then
        If ClipboardW Like "*[" & ChrW(192) & "-" & ChrW(255) & ChrW(168) & ChrW(184) & "]*" Then ' Буфер содержит кракозяблики
            SetClipboardW ClipboardA ' Исправить буфер (засунуть в CF_UNICODETEXT правильную строку взятую из CF_TEXT)
            sndPlaySound wAppPath & "\FixingClipboard.wav", SND_ASYNC Or SND_NODEFAULT
            Exit Sub ' Для ускорения
        End If
    End If
    
    If Len(ClipboardA) > 0 Then
        If IsQuestionString(ClipboardA) = True Then
            ' Если ClipboardW содержит хотябы один русский символ
            If ClipboardW Like "*[А-Яа-яЁё]*" Then
                Clipboard.SetText ClipboardW ' Исправить буфер (засунуть в CF_TEXT правильную строку взятую из CF_UNICODETEXT)
                sndPlaySound wAppPath & "\FixingClipboard.wav", SND_ASYNC Or SND_NODEFAULT
            End If
        End If
    End If
End Sub
 
Private Sub Form_Load()
    Me.Hide
    App.TaskVisible = False
    
    If App.PrevInstance = True Then
        Unload Me
        End
    End If
    
    Call HookSet(Me.hwnd)
End Sub
 
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
    Call HookClear
End Sub
 
Public Sub Callback_ClipboardChange()
    ClipboardPath
End Sub


Код модуля...
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
Option Explicit
 
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 GetWindowSubclass Lib "comctl32" Alias "#411" (ByVal hwnd As Long, ByVal pfnSubclass As Long, ByVal uIdSubclass As Long, pdwRefData 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 SetClipboardViewer Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function ChangeClipboardChain Lib "user32" (ByVal hwnd As Long, ByVal hWndNext As Long) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageW" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
 
Private m_hWnd As Long
Private h_NextClipBoardViewer As Long
Private m_iSubclassed As Long
 
Private Const WM_DRAWCLIPBOARD As Long = &H308&
Private Const WM_CHANGECBCHAIN As Long = &H30D&
Private Const WM_CLIPBOARDUPDATE As Long = &H31D&
Private Const WM_DESTROYCLIPBOARD As Long = &H307&
Private Const WM_NCDESTROY As Long = &H82
Private Const WM_UAHDESTROYWINDOW As Long = &H90&
 
Public Sub HookSet(hWindow As Long)
    If m_iSubclassed = 0 Then
        m_hWnd = hWindow
        m_iSubclassed = SetWindowSubclass(m_hWnd, AddressOf WndProc, 0&)
        h_NextClipBoardViewer = SetClipboardViewer(m_hWnd)
    End If
End Sub
 
Public Sub HookClear()
    If m_iSubclassed Then
        RemoveWindowSubclass m_hWnd, AddressOf WndProc, 0&: m_iSubclassed = 0
        ChangeClipboardChain m_hWnd, h_NextClipBoardViewer
        m_hWnd = 0
    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
    
    Select Case uMsg
        Case WM_NCDESTROY, WM_UAHDESTROYWINDOW
            HookClear
            
        Case WM_DRAWCLIPBOARD
            SendMessage h_NextClipBoardViewer, uMsg, wParam, lParam
            Form1.Callback_ClipboardChange
            bProcessed = True
        
        Case WM_CLIPBOARDUPDATE
            SendMessage h_NextClipBoardViewer, uMsg, wParam, lParam
            Form1.Callback_ClipboardChange
            bProcessed = True
        
        Case WM_CHANGECBCHAIN
           If wParam = h_NextClipBoardViewer Then
                h_NextClipBoardViewer = lParam
           Else
               SendMessage h_NextClipBoardViewer, uMsg, wParam, lParam
           End If
           bProcessed = True
    End Select
    
    If Not bProcessed Then
        WndProc = DefSubclassProc(hwnd, uMsg, wParam, lParam)
    End If
End Function
Вложения
Тип файла: zip ClipboardPath 2.0.zip (15.8 Кб, 207 просмотров)
4
 Аватар для Mikle Quits
766 / 283 / 17
Регистрация: 21.01.2023
Сообщений: 436
04.03.2023, 10:22
Точное измерение промежутков времени.

Поместите в модуле такой код:

Кликните здесь для просмотра всего текста
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
Private Declare Function QueryPerformanceCounter Lib "kernel32" (lpPerformanceCount As Currency) As Long
Private Declare Function QueryPerformanceFrequency Lib "kernel32" (lpFrequency As Currency) As Long
 
Dim QF As Currency
Dim OldQC As Currency
Dim MinCur As Currency
Dim MaxCur As Currency
Dim QTimeVal As Double
 
Public Sub QTimeReset(ByVal Time As Double)
  MaxCur = 922337203685477.5807@
  MinCur = -922337203685477.5807@ - 0.0001@
  QueryPerformanceCounter OldQC
  QueryPerformanceFrequency QF
  QTimeVal = Time
End Sub
 
Public Function QTime() As Double
  Dim QC As Currency
 
  QueryPerformanceCounter QC
  If QC >= OldQC Then
    QTimeVal = QTimeVal + (QC - OldQC) / QF
  Else
    QTimeVal = QTimeVal + ((MaxCur - OldQC) + (QC - MinCur)) / QF
  End If
  OldQC = QC
  QTime = QTimeVal
End Function


Процедурой QTimeReset() инициализируем счётчик стартовым временем.
Функция QTime() возвращает текущее время.
4
 Аватар для Mikle Quits
766 / 283 / 17
Регистрация: 21.01.2023
Сообщений: 436
14.03.2023, 11:44
SR2D. Софтверный движок для работы со спрайтами в VB6.

Вот инструмент, который я написал достаточно давно, но очень часто им пользуюсь.
SR2D работает с 32-битными ARGB спрайтами, умеет загружать их и сохранять в файлы, манипулировать с ними, отображать друг на друга (с эффектами) и на форму (или контролы с hDC).
Для использования SR2D в проекте нужно подключить к проекту модуль modSR2D.bas и класс SR2D_Sprite.cls, а в папку с проектом поместить SR2D.dll.
В движке большое количество возможностей, но, в то же время, для простых задач его использовать очень просто.
Я всё никак не напишу полный мануал на текущую версию (есть мануал на предыдущую, но он сильно устарел), но в предлагаемом архиве есть примеры использования, в том числе самого простого. Если кто-то заинтересуется - я с удовольствием отвечу на вопросы в теме комментариев "Готовых решений", или, если вопросов будет много, можно создать для SR2D отдельную тему.
Вложения
Тип файла: zip SR2D_VB6_Ex.zip (1.31 Мб, 75 просмотров)
4
Испарился
 Аватар для HackerVlad
1741 / 637 / 45
Регистрация: 10.09.2021
Сообщений: 2,769
30.03.2023, 18:58
Баловство: перемещение мышкой абсолютно любых окон-объектов

Ну а теперь давайте отвлечёмся от напряжённой работы и немножко побалуемся! Написал программу-баловство для того чтобы побаловаться с компьютером. Программа для перемещения мышкой абсолютно любых окон и подокон, например кнопок, текстовых полей, листбоксов и так далее. При чём абсолютно где угодно в любой программе. Приятного веселья
Вложения
Тип файла: zip Баловство.zip (8.2 Кб, 65 просмотров)
3
Испарился
 Аватар для HackerVlad
1741 / 637 / 45
Регистрация: 10.09.2021
Сообщений: 2,769
31.03.2023, 00:18
Баловство версия 2.0 значительно улучшенная версия

Наконец-то я доделал полностью эту программку. Исправил все баги, связанные с перемещением окон. Самое сложное было это правильно рассчитать все координаты, теперь всё работает просто идеально. Сложность задачи тут ещё заключалась и в том, что необходимо было рассчитывать количество пикселей заголовков окон, границ окон. Клиентская и неклиентская область окна и так далее. При чём для кажого окна в системе свои значения размеров заголовков, границ и так далее. Где-то есть меню, где-то нету меню. Универсальный рецепт как справиться с задачей я вродебы нашёл при помощи функции ClientToScreen. Но я долго не мог найти ошибку потому как функция ClientToScreen почему-то не перезаписывает значения а просто берёт складывает (добавляет) приплюсовывает к уже существовавшим ранее значениям структуры POINTAPI. Я долго искал этот баг, ели разобрался.

Для кого-то это программа может пригодится и в образовательных целях, кому-то просто повеселиться, а так же можно конечно было бы использовать и для перемещения элементов у себя в своём приложении конечно, но для своего приложения всё гораздо-гораздо проще, достаточно просто пару API-функций и всё, например для того чтобы перемещать элементы у себя в программе, например это кнопка:

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
Option Explicit
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare Function ReleaseCapture Lib "user32" () As Long
 
Private Const WM_NCLBUTTONDOWN = &HA1
Private Const HTCAPTION = 2
 
Private Sub Command1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
    Call ReleaseCapture
    Call SendMessage(Command1.hwnd, WM_NCLBUTTONDOWN, HTCAPTION, 0&)
End Sub
Если бы всё было так просто с элементами в чужих программах! Поэтому и приходится использовать целую кучу других API-функций и хук захвата мыши.

Итак вернёмся к программе. Вот код формы:
Развернуть код...
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
Option Explicit
' *--------------------------------------------*
' | Программа перемещения абсолютно любых окон |
' | Версия 2.0                                 |
' | Copyright (C) 30.03.2023 by HackerVlad     |
' | e-mail: vladislavpeshkov@ya.ru             |
' *--------------------------------------------*
 
Private Declare Function MoveWindow Lib "user32" (ByVal hwnd As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal bRepaint As Long) As Long
Private Declare Function WindowFromPoint Lib "user32" (ByVal xPoint As Long, ByVal yPoint As Long) As Long
Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
Private Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
Private Declare Function ClientToScreen Lib "user32" (ByVal hwnd As Long, ByRef lpPoint As POINTAPI) As Long
Private Declare Function GetParent Lib "user32" (ByVal hwnd As Long) As Long
 
Private Type POINTAPI
    x As Long
    y As Long
End Type
 
Private Type RECT
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
End Type
 
Dim SetCapture As Boolean
Dim rctCapture As RECT
Dim rctCaptureParent As RECT
Dim mouseCapture As POINTAPI
Dim TheHandle As Long
Dim GetParentTheHandle As Long
Dim ScreenXYCoordinates As POINTAPI
 
Private Sub Check2_Click()
    If Check2.Value = 1 Then
        getCtrl = True
    Else
        getCtrl = False
    End If
End Sub
 
Private Sub Command1_Click()
    Unload Me
End Sub
 
Private Sub Form_Load()
    Hook
End Sub
 
Private Sub Form_Unload(Cancel As Integer)
    UnHook
End Sub
 
Public Sub ClickMade()
    SetCapture = True
    
    GetCursorPos mouseCapture
    TheHandle = WindowFromPoint(mouseCapture.x, mouseCapture.y)
    GetParentTheHandle = GetParent(TheHandle)
    
    If GetParentTheHandle > 0 Then
        GetWindowRect TheHandle, rctCapture ' Произвести захват и запомнить изначальное положение элемента
        GetWindowRect GetParentTheHandle, rctCaptureParent
        
        ' Функция ClientToScreen почему-то не перезаписывает заного структуру POINTAPI, а каждый раз прибавляет значения
        ' Поэтому необходимо самому вручную производить обнуление
        ScreenXYCoordinates.x = 0
        ScreenXYCoordinates.y = 0
        ClientToScreen GetParentTheHandle, ScreenXYCoordinates
    End If
End Sub
 
Public Sub ReleaseCapture()
    SetCapture = False
End Sub
 
Public Sub Moving()
    Dim mouse As POINTAPI
    Dim W_Top As Integer
    Dim W_Top2 As Integer
    Dim W_Left As Integer
    Dim W_Left2 As Integer
    Dim W_Width As Integer
    Dim W_Height As Integer
    Dim WidthCaption As Long
    Dim HeightCaption As Long
    
    If SetCapture = True Then
        GetCursorPos mouse
        
        If GetParentTheHandle > 0 Then
            W_Top = mouse.y - (mouseCapture.y - rctCapture.Top)
            W_Top2 = rctCaptureParent.Top
            
            W_Left = mouse.x - (mouseCapture.x - rctCapture.Left)
            W_Left2 = rctCaptureParent.Left
            W_Height = rctCapture.Bottom - rctCapture.Top
            W_Width = rctCapture.Right - rctCapture.Left
            
            WidthCaption = ScreenXYCoordinates.x - rctCaptureParent.Left ' Высота заголовка родительского окна + меню (если есть)
            HeightCaption = ScreenXYCoordinates.y - rctCaptureParent.Top ' Ширина границы рамки родительского окна
            
            MoveWindow TheHandle, (W_Left - W_Left2) - WidthCaption, (W_Top - W_Top2) - HeightCaption, W_Width, W_Height, True
        End If
    End If
End Sub
 
Private Sub mnuExit_Click()
    Unload Me
End Sub


Вот код модуля с хуком мыши:
Развернуть код...
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
Option Explicit
 
Private Type POINTAPI
    x As Long
    y As Long
End Type
 
Private Type MSLLHOOKSTRUCT
    pt As POINTAPI
    mouseData As Long
    flags As Long
    time As Long
    dwExtraInfo As Long
End Type
 
Private Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, ByVal dwThreadId As Long) As Long
Private Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, ByVal ncode As Long, ByVal wParam As Integer, lParam As Any) As Long
Private Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long
Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer
 
Private Const WH_MOUSE_LL = &HE&
Private Const HC_ACTION = 0
Private Const WM_LBUTTONDOWN As Long = &H201
Private Const WM_LBUTTONUP As Long = &H202
Private Const WM_RBUTTONDOWN As Long = &H204
Private Const WM_RBUTTONUP As Long = &H205
Private Const WM_MOUSEMOVE As Long = &H200
 
Dim hMouseHook As Long
Global getCtrl As Boolean
 
Public Sub Hook()
    hMouseHook = SetWindowsHookEx(WH_MOUSE_LL, AddressOf LowLevelMouseProc, App.hInstance, 0)
    If hMouseHook = 0 Then MsgBox ("Mouse hook error")
End Sub
 
Public Sub UnHook()
    If hMouseHook Then UnhookWindowsHookEx (hMouseHook): hMouseHook = 0
End Sub
 
' Процедура перехвата сообщений мыши (мышиный хук)
Private Function LowLevelMouseProc(ByVal uCode As Long, ByVal wParam As Long, lParam As MSLLHOOKSTRUCT) As Long
    If uCode = HC_ACTION Then
        ' Клавиатурный хук для проверки Ctrl я решил уже не использовать: достаточно просто одной функции GetAsyncKeyState
        If getCtrl = True And GetAsyncKeyState(17) = 0 Then Form1.ReleaseCapture: GoTo continue ' Если не нажата клавиша Ctrl
        
        Select Case wParam
            Case WM_LBUTTONDOWN ' Нажатие левой кнопкой мыши
                Form1.ClickMade
                
            Case WM_RBUTTONDOWN ' Нажатие правой кнопкой мыши
                Form1.ClickMade
            
            Case WM_LBUTTONUP
                Form1.ReleaseCapture
                
            Case WM_RBUTTONUP
                Form1.ReleaseCapture
                
            Case WM_MOUSEMOVE
                Form1.Moving
        End Select
    End If
    
continue:
    LowLevelMouseProc = CallNextHookEx(hMouseHook, uCode, wParam, lParam)
End Function


Ну и конечно же прилагаю готовый проект в ZIP-архиве.
Я так же хотел сделать и чтобы перемещались просто обычные окна которые являются родительскими (GetParent = 0) но уже не стал дополнительно заморачиваться, оставлю вам для домашнего задания. Зато! В новой версии добавил возможность перемещать элементы только если нажата клавиша Ctrl. Чтобы случайно не поперемещать то, что Вам не нужно... Успехов!
Вложения
Тип файла: zip Баловство 2.0.zip (10.1 Кб, 61 просмотров)
2
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
31.03.2023, 00:18
Помогаю со студенческими работами здесь

Готовые решения и полезные коды на Visual Basic .NET (Часть-1)
Предлагаю в этой теме размещать ответы на часто задаваемые вопросы и просто делиться полезными кодами. Обращаю внимание на некоторые...

Готовые коды для решения лабораторных работ
Доброго времени суток всем! Очень срочно нужны готовые коды для решения лабораторных работ в С# по учебнику Павловской!!! Вариант 16, нужны...

Написать программу решения квадратного уравнения. В Office Visual Basic
Написать программу решения квадратного уравнения. В Office Visual Basic

Полезные коды и проекты на VBA
В этой теме предлагаю выкладывать различные коды и готовые проекты VBA, которые, на Ваш взгляд, могут помочь новичкам в разработке как...

Полезные коды для PascalABC.NET
В этой теме размещаются полезные исходники программ, различные процедуры и функции, а так же готовые решения на часто задаваемые вопросы,...


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

Или воспользуйтесь поиском по форуму:
300
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
SDL3 для Android: Загрузка PNG с альфа-каналом с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru