Форум программистов, компьютерный форум, киберфорум
The trick
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  

Пользовательская отрисовка окна

Запись от The trick размещена 05.03.2014 в 05:36
Показов 19190 Комментарии 2
Метки basic, vb, win32



В Windows 7 появилась замечательная вещь - индикация прогресса на кнопках панели задач. Чтобы использовать данную возможность на VB6 (и в любых других языках) нужно создать объект TaskBarList, получить интерфейс ITaskBarList3 и воспользоваться его методами SetProgressState и SetProgressValue.
В своем модуле я добавил возможность задавать состояние индикатора прогресса на панели задач, а также продублировал этот индикатор на саму форму + добавил возможность использования анимированных иконок в заголовке формы (также поддерживаются и обычные иконки). Из данного примера можно узнать, как самому отрисовывать неклиентскую область окна, делать кнопки которые подсвечиваются при наведении. В примере используется двойная буфферизация, поэтому все работает гладко и без мерцаний. Данный модуль можно прециплять к любому проекту с любыми формами.
Модуль:
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
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
Option Explicit
 
' Модуль пользовательской отрисовки неклиентской области окна
' + поддержка индикатора прогресса панели задач (Win7)
' © Кривоус Анатолий Анатольевич (The trick), 2014
 
Private Const LF_FACESIZE = 32
 
Private Type RECT
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
End Type
Private Type AnimIcon
    Sequence As Long
    NumOfFrame As Long
    CurFrame As Long
    State As Long
    Interval As Long
    Looped As Boolean
End Type
Private Type WndExtInfo
    lpOldWndProc As Long
    ProgressValue As Single
    ProgressState As Taskbarlib.TBPFLAG
    Icon As AnimIcon
    ButtonsState As Long
End Type
Private Type StatePicture
    Active As StdPicture
    Inactive As StdPicture
End Type
Private Type NCCALCSIZE_PARAMS
    rgrc(2) As RECT
    lpWindowPos As Long
End Type
Private Type POINTAPI
    x As Long
    y As Long
End Type
Private Type tagTRACKMOUSEEVENT
    cbSize As Long
    dwFlags As Long
    hwndTrack As Long
    dwHoverTime As Long
End Type
Private Type LOGFONT
    lfHeight As Long
    lfWidth As Long
    lfEscapement As Long
    lfOrientation As Long
    lfWeight As Long
    lfItalic As Byte
    lfUnderline As Byte
    lfStrikeOut As Byte
    lfCharSet As Byte
    lfOutPrecision As Byte
    lfClipPrecision As Byte
    lfQuality As Byte
    lfPitchAndFamily As Byte
    lfFaceName(1 To LF_FACESIZE) As Byte
End Type
Private Type NONCLIENTMETRICS
    cbSize As Long
    iBorderWidth As Long
    iScrollWidth As Long
    iScrollHeight As Long
    iCaptionWidth As Long
    iCaptionHeight As Long
    lfCaptionFont As LOGFONT
    iSMCaptionWidth As Long
    iSMCaptionHeight As Long
    lfSMCaptionFont As LOGFONT
    iMenuWidth As Long
    iMenuHeight As Long
    lfMenuFont As LOGFONT
    lfStatusFont As LOGFONT
    lfMessageFont As LOGFONT
End Type
 
Private Declare Function TrackMouseEvent Lib "user32" (ByRef lpEventTrack As tagTRACKMOUSEEVENT) As Long
Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function HeapCreate Lib "kernel32" (ByVal flOptions As Long, ByVal dwInitialSize As Long, ByVal dwMaximumSize As Long) As Long
Private Declare Function HeapAlloc Lib "kernel32" (ByVal hHeap As Long, ByVal dwFlags As Long, ByVal dwBytes As Long) As Long
Private Declare Function HeapDestroy Lib "kernel32" (ByVal hHeap As Long) As Long
Private Declare Function HeapFree Lib "kernel32" (ByVal hHeap As Long, ByVal dwFlags As Long, lpMem As Any) As Long
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function GetMem4 Lib "msvbvm60" (Src As Any, Dst As Any) As Long
Private Declare Function GetMem8 Lib "msvbvm60" (Src As Any, Dst As Any) As Long
Private Declare Function GetDCEx Lib "user32" (ByVal hwnd As Long, ByVal hrgnclip As Long, ByVal fdwOptions As Long) As Long
Private Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
Private Declare Function SetWindowRgn Lib "user32" (ByVal hwnd As Long, ByVal hRgn As Long, ByVal bRedraw As Long) As Long
Private Declare Function CreateRectRgn Lib "gdi32" (ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As Long
Private Declare Function CombineRgn Lib "gdi32" (ByVal hDestRgn As Long, ByVal hSrcRgn1 As Long, ByVal hSrcRgn2 As Long, ByVal nCombineMode As Long) As Long
Private Declare Function OffsetRgn Lib "gdi32" (ByVal hRgn As Long, ByVal x As Long, ByVal y As Long) As Long
Private Declare Function CreateRoundRectRgn Lib "gdi32" (ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long, ByVal X3 As Long, ByVal Y3 As Long) As Long
Private Declare Function RedrawWindow Lib "user32" (ByVal hwnd As Long, lprcUpdate As Any, ByVal hrgnUpdate As Long, ByVal fuRedraw As Long) As Long
Private Declare Function GetActiveWindow Lib "user32" () As Long
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 GetSystemMetrics Lib "user32" (ByVal nIndex As Long) As Long
Private Declare Function DefWindowProc Lib "user32" Alias "DefWindowProcA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Integer, ByVal lParam As Long) As Long
Private Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer
Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As Long
Private Declare Function CreateCompatibleBitmap Lib "gdi32" (ByVal hdc As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long
Private Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal hObject As Long) As Long
Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
Private Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long
Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hdc As Long) As Long
Private Declare Function GetDesktopWindow Lib "user32" () As Long
Private Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long
Private Declare Function StretchBlt Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal nSrcWidth As Long, ByVal nSrcHeight As Long, ByVal dwRop As Long) As Long
Private Declare Function ExcludeClipRect Lib "gdi32" (ByVal hdc As Long, ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As Long
Private Declare Function IntersectClipRect Lib "gdi32" (ByVal hdc As Long, ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As Long
Private Declare Function SelectClipRgn Lib "gdi32" (ByVal hdc As Long, ByVal hRgn As Long) As Long
Private Declare Function SetCapture Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function ClientToScreen Lib "user32" (ByVal hwnd As Long, lpPoint As POINTAPI) As Long
Private Declare Function ReleaseCapture Lib "user32" () As Long
Private Declare Function IsZoomed Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare Function DrawText Lib "user32" Alias "DrawTextW" (ByVal hdc As Long, ByVal lpStr As Long, ByVal nCount As Long, lpRect As RECT, ByVal wFormat As Long) As Long
Private Declare Function SetTextColor Lib "gdi32" (ByVal hdc As Long, ByVal crColor As Long) As Long
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextW" (ByVal hwnd As Long, ByVal lpString As Long, ByVal cch As Long) As Long
Private Declare Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthW" (ByVal hwnd As Long) As Long
Private Declare Function SetRect Lib "user32" (lpRect As RECT, ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As Long
Private Declare Function SystemParametersInfo Lib "user32" Alias "SystemParametersInfoA" (ByVal uAction As Long, ByVal uParam As Long, ByRef lpvParam As Any, ByVal fuWinIni As Long) As Long
Private Declare Function CreateFontIndirect Lib "gdi32" Alias "CreateFontIndirectA" (lpLogFont As LOGFONT) As Long
Private Declare Function CreateBitmap Lib "gdi32" (ByVal nWidth As Long, ByVal nHeight As Long, ByVal nPlanes As Long, ByVal nBitCount As Long, lpBits As Any) As Long
Private Declare Function SetBkMode Lib "gdi32" (ByVal hdc As Long, ByVal nBkMode As Long) As Long
Private Declare Function DrawIconEx Lib "user32" (ByVal hdc As Long, ByVal xLeft As Long, ByVal yTop As Long, ByVal hIcon As Long, ByVal cxWidth As Long, ByVal cyWidth As Long, ByVal istepIfAniCur As Long, ByVal hbrFlickerFreeDraw As Long, ByVal diFlags As Long) As Long
Private Declare Function AlphaBlend Lib "msimg32.dll" (ByVal hdc As Long, ByVal lInt As Long, ByVal lInt As Long, ByVal lInt As Long, ByVal lInt As Long, ByVal hdc As Long, ByVal lInt As Long, ByVal lInt As Long, ByVal lInt As Long, ByVal lInt As Long, ByVal BLENDFUNCT As Long) As Long
Private Declare Sub vbaObjAddRef Lib "msvbvm60.dll" Alias "__vbaObjAddref" (nClass As Any)
Private Declare Sub vbaObjSet Lib "msvbvm60.dll" Alias "__vbaObjSet" (Dst As Any, Src As Any)
Private Declare Function SetTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
Private Declare Function KillTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long) As Long
 
Private Const TRANSPARENT = 1
Private Const SPI_GETNONCLIENTMETRICS = 41
Private Const HEAP_NO_SERIALIZE = &H1
Private Const GWL_WNDPROC = &HFFFFFFFC
Private Const GWL_USERDATA = (-21)
Private Const GWL_STYLE = (-16)
Private Const GWL_EXSTYLE = (-20)
Private Const WS_EX_TOOLWINDOW = &H80&
Private Const WS_EX_CONTEXTHELP = &H400&
Private Const WS_MAXIMIZEBOX = &H10000
Private Const WS_MINIMIZEBOX = &H20000
Private Const DCX_WINDOW = &H1&
Private Const DCX_INTERSECTRGN = &H80&
Private Const DCX_CLIPSIBLINGS = &H10&
Private Const SIZE_MINIMIZED = 1
Private Const SIZE_MAXIMIZED = 2
Private Const RGN_OR = 2
Private Const RDW_FRAME = &H400
Private Const RDW_INVALIDATE = &H1
Private Const HTLEFT = 10
Private Const HTTOP = 12
Private Const HTRIGHT = 11
Private Const HTBOTTOM = 15
Private Const HTTOPLEFT = 13
Private Const HTTOPRIGHT = 14
Private Const HTBOTTOMRIGHT = 17
Private Const HTBOTTOMLEFT = 16
Private Const HTCAPTION = 2
Private Const HTCLIENT = 1
Private Const HTCLOSE = 20
Private Const HTMAXBUTTON = 9
Private Const HTMINBUTTON = 8
Private Const HTSYSMENU = 3
Private Const HTHELP = 21
Private Const HTTRANSPARENT = (-1)
Private Const TME_LEAVE = &H2
Private Const TME_QUERY = &H40000000
Private Const TME_NONCLIENT = &H10
Private Const TME_CANCEL = &H80000000
Private Const WS_THICKFRAME = &H40000
Private Const VK_LBUTTON = &H1
Private Const SC_CLOSE = &HF060&
Private Const SC_CONTEXTHELP = &HF180&
Private Const SC_MAXIMIZE = &HF030&
Private Const SC_MINIMIZE = &HF020&
Private Const SC_RESTORE = &HF120&
Private Const DT_END_ELLIPSIS = &H8000&
Private Const RDW_UPDATENOW = &H100
Private Const ICON_BIG = 1
Private Const DI_NORMAL = 3
Private Const AB_32Bpp255 = 33488896
 
Private Const WM_NCPAINT = &H85
Private Const WM_NCCALCSIZE = &H83
Private Const WM_NCACTIVATE = &H86
Private Const WM_NCUAHDRAWCAPTION = &HAE
Private Const WM_NCHITTEST = &H84
Private Const WM_NCLBUTTONDOWN = &HA1
Private Const WM_NCMOUSEMOVE = &HA0
Private Const WM_NCMOUSELEAVE = &H2A2
Private Const WM_SYSCOMMAND = &H112
Private Const WM_SIZE = &H5
Private Const WM_POPUPSYSTEMMENU = &H313
Private Const WM_MOUSEMOVE = &H200
Private Const WM_LBUTTONUP = &H202
Private Const WM_GETICON = &H7F&
Private Const WM_TIMER = &H113
 
Private Const SIZE_CAPTION = 38
Private Const SIZE_BORDER = 4
Private Const SIZE_ICON = 32
Private Const BUT_CLOSE = 0
Private Const BUT_MAX = 1
Private Const BUT_MIN = 2
Private Const BUT_HELP = 3
Private Const BUT_SPACING = 4
Private Const STA_OVER = 1
Private Const STA_DOWN = 2
 
Dim hHeap               As Long
Dim wCount              As Long
Dim bufDC               As Long
Dim buf2DC              As Long
Dim bufBmp              As Long
Dim bufoBmp             As Long
Dim picInit             As Boolean
Dim picWnd              As StatePicture
Dim picBut()            As StdPicture
Dim picPrg              As StatePicture
Dim sysnc               As NONCLIENTMETRICS
Dim capFont             As Long
Dim Task                As Taskbarlib.TaskbarList
 
' Установить стиль отрисовки окну
Public Function SetNCSkin(frm As Form) As Boolean
    Dim wi As WndExtInfo, pt As Long
    pt = GetWindowLong(frm.hwnd, GWL_USERDATA)
    If pt Then Exit Function
    If Not picInit Then LoadSkin
    If hHeap = 0 Then
        hHeap = HeapCreate(HEAP_NO_SERIALIZE, Len(wi), 0)
        If hHeap = 0 Then Exit Function
    End If
    pt = HeapAlloc(hHeap, HEAP_NO_SERIALIZE, Len(wi))
    If pt = 0 Then
        If wCount = 0 Then HeapDestroy hHeap: hHeap = 0
        Exit Function
    End If
    wCount = wCount + 1
    wi.ProgressState = TBPF_NOPROGRESS
    wi.ProgressValue = 0
    wi.lpOldWndProc = SetWindowLong(frm.hwnd, GWL_WNDPROC, AddressOf WndProc)
    SetWindowLong frm.hwnd, GWL_USERDATA, pt
    CopyMemory ByVal pt, wi, Len(wi)
    SetNCSkin = True
End Function
' Убрать стиль отрисовки у окна
Public Function RemoveNCSkin(frm As Form) As Boolean
    Dim wi As WndExtInfo, pt As Long, bmp As StdPicture
    If hHeap = 0 Or wCount = 0 Then Exit Function
    pt = GetWindowLong(frm.hwnd, GWL_USERDATA)
    If pt = 0 Then Exit Function
    CopyMemory wi, ByVal pt, Len(wi)
    SetWindowLong frm.hwnd, GWL_WNDPROC, wi.lpOldWndProc
    SetWindowLong frm.hwnd, GWL_USERDATA, 0
    HeapFree hHeap, HEAP_NO_SERIALIZE, ByVal pt
    wCount = wCount - 1
    If wCount = 0 Then
        DeleteDC bufDC
        SelectObject buf2DC, bufoBmp
        DeleteDC buf2DC
        DeleteObject bufBmp
        DeleteObject capFont
        HeapDestroy hHeap: hHeap = 0
        Set Task = Nothing
    End If
    RemoveNCSkin = True
End Function
' Установить анимированную иконку окну с пользовательскм стилем отрисовки
Public Function SetIcon(frm As Form, Icon As StdPicture, ByVal NumFrames As Long) As Boolean
    Dim wi As WndExtInfo, rc As RECT
    If Not GetExtInfo(frm.hwnd, wi) Then Exit Function
    wi.Icon.CurFrame = 0
    wi.Icon.NumOfFrame = NumFrames
    wi.Icon.State = 0
    wi.Icon.Sequence = ObjPtr(Icon)
    SetExtInfo frm.hwnd, wi
    vbaObjAddRef ByVal wi.Icon.Sequence
    SetRect rc, -SIZE_BORDER, -SIZE_CAPTION, SIZE_ICON, 0
    RedrawWindow frm.hwnd, rc, 0, RDW_FRAME Or RDW_INVALIDATE
    SetIcon = True
End Function
' Проиграть анимацию в окне с пользовательским стилем отрисовки
Public Function PlayAnimation(frm As Form, Optional ByVal IntervalMS As Long = 100, Optional ByVal Looped As Boolean = False) As Boolean
    Dim wi As WndExtInfo
    If Not GetExtInfo(frm.hwnd, wi) Then Exit Function
    wi.Icon.CurFrame = 0
    wi.Icon.State = 1
    wi.Icon.Looped = Looped
    SetExtInfo frm.hwnd, wi
    SetTimer frm.hwnd, frm.hwnd, IntervalMS, 0
    PlayAnimation = True
End Function
' Остановить анимацию в окне с пользовательским стилем отрисовки
Public Function StopAnimation(frm As Form) As Boolean
    Dim wi As WndExtInfo, hdc As Long
    If Not GetExtInfo(frm.hwnd, wi) Then Exit Function
    If wi.Icon.State = 1 Then KillTimer frm.hwnd, frm.hwnd
    wi.Icon.State = 0
    wi.Icon.CurFrame = 0
    SetExtInfo frm.hwnd, wi
    hdc = GetDCEx(frm.hwnd, 0, DCX_WINDOW Or DCX_CLIPSIBLINGS)
    myDrawIcon frm.hwnd, buf2DC
    BitBlt hdc, SIZE_BORDER, 0, SIZE_ICON, SIZE_CAPTION, buf2DC, SIZE_BORDER, 0, vbSrcCopy
    ReleaseDC frm.hwnd, hdc
    StopAnimation = True
End Function
' Задать состояние индикатора прогресса в окне с пользовательским стилем отрисовки и на панели задач (Win7)
Public Function SetProgressState(frm As Form, ByVal State As Taskbarlib.TBPFLAG) As Boolean
    Dim wi As WndExtInfo
    If Not GetExtInfo(frm.hwnd, wi) Then Exit Function
    wi.ProgressState = State
    SetExtInfo frm.hwnd, wi
    InvalidateProgress frm.hwnd
    SetProgressState = True
    If Not Task Is Nothing Then Task.SetProgressState frm.hwnd, State
End Function
' Получить состояние индикатора прогресса в окне с пользовательским стилем отрисовки и на панели задач (Win7)
Public Function GetProgressState(frm As Form) As Taskbarlib.TBPFLAG
    Dim wi As WndExtInfo
    If Not GetExtInfo(frm.hwnd, wi) Then Exit Function
    GetProgressState = wi.ProgressState
End Function
' Задать значение индикатора прогресса в окне с пользовательским стилем отрисовки и на панели задач (Win7)
Public Function SetProgressValue(frm As Form, ByVal Value As Single) As Boolean
    Dim wi As WndExtInfo
    If Value < 0 Or Value > 1 Then Exit Function
    If Not GetExtInfo(frm.hwnd, wi) Then Exit Function
    wi.ProgressValue = Value
    SetExtInfo frm.hwnd, wi
    SetProgressValue = True
    If wi.ProgressState <> TBPF_NOPROGRESS Then InvalidateProgress frm.hwnd
    If Not Task Is Nothing Then Task.SetProgressValue frm.hwnd, CCur(Value * 10000), CCur(10000)
End Function
' Получить значение индикатора прогресса в окне с пользовательским стилем отрисовки и на панели задач (Win7)
Public Function GetProgressValue(frm As Form) As Single
    Dim wi As WndExtInfo
    If Not GetExtInfo(frm.hwnd, wi) Then Exit Function
    GetProgressValue = wi.ProgressValue
End Function
Private Function GetExtInfo(ByVal hwnd As Long, wi As WndExtInfo) As Boolean
    Dim pt As Long
    If hHeap = 0 Or wCount = 0 Then Exit Function
    pt = GetWindowLong(hwnd, GWL_USERDATA)
    If pt = 0 Then Exit Function
    CopyMemory wi, ByVal pt, Len(wi)
    GetExtInfo = True
End Function
Private Function SetExtInfo(ByVal hwnd As Long, wi As WndExtInfo) As Boolean
    Dim pt As Long
    If hHeap = 0 Or wCount = 0 Then Exit Function
    pt = GetWindowLong(hwnd, GWL_USERDATA)
    If pt = 0 Then Exit Function
    CopyMemory ByVal pt, wi, Len(wi)
    SetExtInfo = True
End Function
Private Function LoadSkin() As Boolean
    Dim dhwnd As Long, ddc As Long
    Set picWnd.Active = LoadResPicture("ACTIVEWINDOW", vbResBitmap)
    Set picWnd.Inactive = LoadResPicture("INACTIVEWINDOW", vbResBitmap)
    Set picPrg.Active = LoadResPicture("PROGRESSACTIVE", vbResBitmap)
    Set picPrg.Inactive = LoadResPicture("PROGRESSINACTIVE", vbResBitmap)
    ReDim picBut(3)
    Set picBut(BUT_CLOSE) = LoadResPicture("CLOSEBUTTON", vbResBitmap)
    Set picBut(BUT_MAX) = LoadResPicture("MAXIMIZEBUTTON", vbResBitmap)
    Set picBut(BUT_MIN) = LoadResPicture("MINIMIZEBUTTON", vbResBitmap)
    Set picBut(BUT_HELP) = LoadResPicture("HELPBUTTON", vbResBitmap)
    
    dhwnd = GetDesktopWindow()
    ddc = GetDC(dhwnd)
    bufDC = CreateCompatibleDC(ddc)
    buf2DC = CreateCompatibleDC(ddc)
    SetBkMode buf2DC, TRANSPARENT
    ReleaseDC dhwnd, ddc
    
    sysnc.cbSize = Len(sysnc)
    SystemParametersInfo SPI_GETNONCLIENTMETRICS, Len(sysnc), sysnc, 0
    
    capFont = CreateFontIndirect(sysnc.lfCaptionFont)
 
    bufBmp = CreateBitmap(2048, SIZE_CAPTION, 1, 32, ByVal 0)
    bufoBmp = SelectObject(buf2DC, bufBmp)
 
    On Error Resume Next
    Set Task = New Taskbarlib.TaskbarList
    picInit = True
End Function
Private Function WndProc(ByVal hwnd As Long, ByVal msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Select Case msg
    Case WM_NCUAHDRAWCAPTION
    Case WM_LBUTTONUP
        WndProc = OnLButtonUp(hwnd, wParam, lParam)
    Case WM_MOUSEMOVE
        WndProc = OnMouseMove(hwnd, wParam, lParam)
    Case WM_NCMOUSELEAVE
        WndProc = OnNCMouseLeave(hwnd)
    Case WM_NCMOUSEMOVE
        WndProc = OnNCMouseMove(hwnd, wParam, lParam)
    Case WM_NCLBUTTONDOWN
        WndProc = OnNCLButtonDown(hwnd, wParam, lParam)
    Case WM_NCHITTEST
        WndProc = OnNCHitTest(hwnd, lParam And &HFFFF&, (lParam \ &H10000) And &HFFFF&)
    Case WM_SIZE
        WndProc = OnSize(hwnd, wParam, lParam And &HFFFF&, (lParam \ &H10000) And &HFFFF&)
    Case WM_NCPAINT
        WndProc = OnNCPaint(hwnd, wParam)
    Case WM_NCCALCSIZE
        WndProc = OnNCCalcSize(hwnd, wParam, lParam)
    Case WM_NCACTIVATE
        WndProc = OnNCActivate(hwnd, wParam)
    Case WM_TIMER
        WndProc = OnTimer(hwnd, wParam, lParam)
    Case Else
        WndProc = CallOldWndProc(hwnd, msg, wParam, lParam)
    End Select
End Function
Private Function CallOldWndProc(ByVal hwnd As Long, ByVal msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Dim lpOldProc As Long, OldProc As Long
    lpOldProc = GetWindowLong(hwnd, GWL_USERDATA)
    GetMem4 ByVal lpOldProc, OldProc
    CallOldWndProc = CallWindowProc(OldProc, hwnd, msg, wParam, lParam)
End Function
'\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\Процедуры окна\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
Private Function OnNCPaint(ByVal hwnd As Long, hRgn As Long) As Long
    Dim rc As RECT, hdc As Long, pic As StdPicture, Btn() As Long, i As Long, x As Long, y As Long, iw As Long, st As Long, _
        ct As Long, txt As String, bwa As LogEventTypeConstants, ofnt As Long, wi As WndExtInfo, capw As Long, rctxt As RECT
    
    GetWindowRect hwnd, rc
    If GetActiveWindow() = hwnd Then Set pic = picWnd.Active: st = 0 Else Set pic = picWnd.Inactive: st = 3
 
    If hRgn <> 1 Then
        hdc = GetDCEx(hwnd, hRgn, DCX_WINDOW Or DCX_INTERSECTRGN Or DCX_CLIPSIBLINGS)
        DrawBevel hdc, pic, 0, 0, rc.Right - rc.Left, rc.Bottom - rc.Top, SIZE_ICON + SIZE_BORDER, SIZE_CAPTION, SIZE_BORDER, SIZE_BORDER
    Else
        hdc = GetDCEx(hwnd, 0, DCX_WINDOW Or DCX_CLIPSIBLINGS)
        ExcludeClipRect hdc, SIZE_BORDER, SIZE_CAPTION, rc.Right - rc.Left - SIZE_BORDER, _
                        rc.Bottom - rc.Top - SIZE_BORDER
        DrawBevel hdc, pic, 0, 0, rc.Right - rc.Left, rc.Bottom - rc.Top, SIZE_ICON + SIZE_BORDER, SIZE_CAPTION, SIZE_BORDER, SIZE_BORDER
        SelectClipRgn hdc, 0
    End If
    
    GetButtons hwnd, Btn()
    x = rc.Right - rc.Left - SIZE_BORDER - BUT_SPACING
    y = 8 + BUT_SPACING + SIZE_BORDER
    For i = 0 To UBound(Btn)
        iw = picBut(Btn(i)).Width / 2540 * (1440 / Screen.TwipsPerPixelX)
        DrawStateButton buf2DC, x - iw, y, Btn(i), st
        x = x - iw - BUT_SPACING
        bwa = bwa + iw + BUT_SPACING
    Next
    
    capw = rc.Right - rc.Left - SIZE_BORDER * 4 - bwa - SIZE_ICON
    GetExtInfo hwnd, wi
    If GetActiveWindow() = hwnd Then Set pic = picPrg.Active Else Set pic = picPrg.Inactive
    
    If wi.ProgressState <> TBPF_NOPROGRESS Then
        DrawProgress buf2DC, SIZE_BORDER * 2 + SIZE_ICON, 8 + SIZE_BORDER, capw, pic, wi.ProgressState, wi.ProgressValue
    End If
    
    ct = GetWindowTextLength(hwnd)
    txt = Space(ct)
    GetWindowText hwnd, StrPtr(txt), ct
    SetRect rctxt, SIZE_BORDER * 3 + SIZE_ICON, 8 + SIZE_BORDER * 2, capw + SIZE_BORDER * 2 + SIZE_ICON, 8 + SIZE_CAPTION
    ofnt = SelectObject(buf2DC, capFont)
    DrawText buf2DC, StrPtr(txt), ct, rctxt, DT_END_ELLIPSIS
    SelectObject buf2DC, ofnt
    
    myDrawIcon hwnd, buf2DC
    
    BitBlt hdc, 0, 0, rc.Right - rc.Left, SIZE_CAPTION, buf2DC, 0, 0, vbSrcCopy
    
    ReleaseDC hwnd, hdc
End Function
Private Function OnTimer(ByVal hwnd As Long, ByVal ID As Long, ByVal lpTimFunc As Long) As Long
    Dim wi As WndExtInfo, hdc As Long
    If hwnd = ID Then
        GetExtInfo hwnd, wi
        wi.Icon.CurFrame = wi.Icon.CurFrame + 1
        If wi.Icon.CurFrame >= wi.Icon.NumOfFrame Then
            wi.Icon.CurFrame = 0
            If Not wi.Icon.Looped Then
                wi.Icon.State = 0
                KillTimer hwnd, ID
            End If
        End If
        SetExtInfo hwnd, wi
        myDrawIcon hwnd, buf2DC
        hdc = GetDCEx(hwnd, 0, DCX_WINDOW Or DCX_CLIPSIBLINGS)
        BitBlt hdc, SIZE_BORDER, 0, SIZE_ICON, SIZE_CAPTION, buf2DC, SIZE_BORDER, 0, vbSrcCopy
        ReleaseDC hwnd, hdc
    Else
        OnTimer = CallOldWndProc(hwnd, WM_TIMER, ID, lpTimFunc)
    End If
End Function
Private Function OnMouseMove(ByVal hwnd As Long, ByVal Btn As Long, ByVal CursorPos As Long) As Long
    Dim stat As Long, pt As POINTAPI, pos As Long, cbtn As Long, obtn As Long
    GetMem4 ByVal GetWindowLong(hwnd, GWL_USERDATA) + 34, stat
    obtn = (stat And &HF00) \ &H100
    If obtn Then
        pt.x = IIf(CursorPos And &H8000&, CursorPos Or &HFFFF0000, CursorPos And &HFFFF&)
        pt.y = CursorPos \ &H10000
        ClientToScreen hwnd, pt
        pos = SendMessage(hwnd, WM_NCHITTEST, 0, ByVal pt.x Or (pt.y * &H10000))
        cbtn = GetBtnIndex(pos)
        UpdateButtons hwnd, pos, obtn - 1
    End If
    OnMouseMove = CallOldWndProc(hwnd, WM_MOUSEMOVE, Btn, CursorPos)
End Function
Private Function OnNCMouseLeave(ByVal hwnd As Long) As Long
    UpdateButtons hwnd, 0
End Function
Private Function OnNCMouseMove(ByVal hwnd As Long, ByVal pos As Long, ByVal CursorPos As Long) As Long
    Dim TME As tagTRACKMOUSEEVENT
    TME.cbSize = Len(TME)
    TME.dwFlags = TME_QUERY
    TrackMouseEvent TME
    If TME.hwndTrack <> hwnd Then
        TME.dwFlags = TME_LEAVE Or TME_NONCLIENT
        TME.hwndTrack = hwnd
        TrackMouseEvent TME
    End If
    UpdateButtons hwnd, pos
    OnNCMouseMove = CallOldWndProc(hwnd, WM_NCMOUSEMOVE, pos, CursorPos)
End Function
Private Function OnLButtonUp(ByVal hwnd As Long, ByVal Btn As Long, ByVal CursorPos As Long) As Long
    Dim stat As Long, pt As POINTAPI, pos As Long, btnidx As Long
    
    ReleaseCapture
    GetMem4 ByVal GetWindowLong(hwnd, GWL_USERDATA) + 34, stat
    stat = (stat And &HF00) \ &H100
    If stat Then
        pt.x = IIf(CursorPos And &H8000&, CursorPos Or &HFFFF0000, CursorPos And &HFFFF&)
        pt.y = CursorPos \ &H10000
        ClientToScreen hwnd, pt
        pos = SendMessage(hwnd, WM_NCHITTEST, 0, ByVal pt.x Or (pt.y * &H10000))
        btnidx = GetBtnIndex(pos)
        UpdateButtons hwnd, pos, btnidx
        If stat - 1 = btnidx Then
            Select Case btnidx
            Case BUT_CLOSE: PostMessage hwnd, WM_SYSCOMMAND, SC_CLOSE, ByVal 0
            Case BUT_MAX: If IsZoomed(hwnd) Then PostMessage hwnd, WM_SYSCOMMAND, SC_RESTORE, ByVal 0 _
                                                Else: PostMessage hwnd, WM_SYSCOMMAND, SC_MAXIMIZE, ByVal 0
            Case BUT_MIN: PostMessage hwnd, WM_SYSCOMMAND, SC_MINIMIZE, ByVal 0
            Case BUT_HELP: PostMessage hwnd, WM_SYSCOMMAND, SC_CONTEXTHELP, ByVal 0
            End Select
        End If
        GetMem4 stat And &HFF&, ByVal GetWindowLong(hwnd, GWL_USERDATA) + 34
    End If
    OnLButtonUp = CallOldWndProc(hwnd, WM_LBUTTONUP, pos, CursorPos)
End Function
Private Function OnNCLButtonDown(ByVal hwnd As Long, ByVal pos As Long, ByVal CursorPos As Long) As Long
    Dim stat As Long, btnidx As Long, TME As tagTRACKMOUSEEVENT
    TME.cbSize = Len(TME)
    TME.dwFlags = TME_QUERY
    TrackMouseEvent TME
    If TME.hwndTrack = hwnd Then
        TME.dwFlags = TME_CANCEL Or TME_LEAVE Or TME_NONCLIENT
        TME.hwndTrack = hwnd
        TrackMouseEvent TME
    End If
    Select Case pos
    Case HTSYSMENU
        SendMessage hwnd, WM_POPUPSYSTEMMENU, 0, ByVal CursorPos
    Case HTCLOSE, HTMAXBUTTON, HTMINBUTTON, HTHELP
        GetMem4 ByVal GetWindowLong(hwnd, GWL_USERDATA) + 34, stat
        btnidx = GetBtnIndex(pos)
        stat = stat Or (&H100& * (btnidx + 1))
        GetMem4 stat, ByVal GetWindowLong(hwnd, GWL_USERDATA) + 34
        UpdateButtons hwnd, pos
        SetCapture hwnd
    Case Else
        OnNCLButtonDown = CallOldWndProc(hwnd, WM_NCLBUTTONDOWN, pos, CursorPos)
    End Select
End Function
Private Function OnSize(ByVal hwnd As Long, ByVal State As Long, ByVal w As Long, ByVal h As Long) As Long
    Dim hRgn1 As Long, hRgn2 As Long, rw As Long, rh As Long
    If State = SIZE_MINIMIZED Or State = SIZE_MAXIMIZED Then
        SetWindowRgn hwnd, 0, True
    Else
        rw = w + SIZE_BORDER * 2
        rh = h + SIZE_BORDER + SIZE_CAPTION
        
        hRgn1 = CreateRoundRectRgn(0, 8, rw + 1, rh + 1, 4, 4)
        hRgn2 = CreateRectRgn(4, 0, 37, 8)
        CombineRgn hRgn1, hRgn1, hRgn2, RGN_OR
        DeleteObject hRgn2
        SetWindowRgn hwnd, hRgn1, True
    End If
End Function
Private Function OnNCHitTest(ByVal hwnd As Long, ByVal x As Long, ByVal y As Long) As Long
    Dim rc As RECT, w As Long, h As Long, sizbl As Boolean, Btn() As Long, i As Long, _
        px As Long, py As Long, iw As Long, ih As Long
    
    GetWindowRect hwnd, rc
    sizbl = GetWindowLong(hwnd, GWL_STYLE) And WS_THICKFRAME
    GetButtons hwnd, Btn()
    
    x = x - rc.Left: y = y - rc.Top: w = rc.Right - rc.Left: h = rc.Bottom - rc.Top
    Select Case True
    Case x > SIZE_BORDER And x < SIZE_BORDER + SIZE_ICON And _
         y >= 0 And y < SIZE_CAPTION
        OnNCHitTest = HTSYSMENU
    
    Case x <= SIZE_BORDER And x >= 0 And sizbl
        Select Case y
        Case Is < 8: OnNCHitTest = HTTRANSPARENT
        Case Is <= 8 + SIZE_BORDER: OnNCHitTest = HTTOPLEFT
        Case Is <= h - SIZE_BORDER: OnNCHitTest = HTLEFT
        Case Else: OnNCHitTest = HTBOTTOMLEFT
        End Select
    Case x > SIZE_BORDER And x < w - SIZE_BORDER And sizbl
        Select Case y
        Case Is < 8: OnNCHitTest = HTTRANSPARENT
        Case Is <= 8 + SIZE_BORDER: OnNCHitTest = HTTOP
        Case Is <= SIZE_CAPTION: OnNCHitTest = HTCAPTION
        Case Is <= h - SIZE_BORDER: OnNCHitTest = HTCLIENT
        Case Else: OnNCHitTest = HTBOTTOM
        End Select
    Case x >= w - SIZE_BORDER And x <= w And sizbl
        Select Case y
        Case Is < 8: OnNCHitTest = HTTRANSPARENT
        Case Is <= 8 + SIZE_BORDER: OnNCHitTest = HTTOPRIGHT
        Case Is <= h - SIZE_BORDER: OnNCHitTest = HTRIGHT
        Case Else: OnNCHitTest = HTBOTTOMRIGHT
        End Select
    End Select
    If OnNCHitTest = 0 Or OnNCHitTest = HTCAPTION Then
        px = w - SIZE_BORDER - BUT_SPACING: py = 8 + BUT_SPACING + SIZE_BORDER
        If y >= py Then
            For i = 0 To UBound(Btn)
                iw = picBut(Btn(i)).Width / 2540 * (1440 / Screen.TwipsPerPixelX)
                ih = picBut(Btn(i)).Height / 2540 * (1440 / Screen.TwipsPerPixelY) \ 5
                If x >= px - iw And x <= px And y <= py + ih Then
                    Select Case i
                    Case BUT_CLOSE: OnNCHitTest = HTCLOSE
                    Case BUT_MAX: OnNCHitTest = HTMAXBUTTON
                    Case BUT_MIN: OnNCHitTest = HTMINBUTTON
                    Case BUT_HELP: OnNCHitTest = HTHELP
                    End Select
                    Exit Function
                End If
                px = px - iw - BUT_SPACING
            Next
            OnNCHitTest = HTCAPTION
        End If
    End If
End Function
Private Function OnNCActivate(ByVal hwnd As Long, ByVal State As Boolean) As Long
    RedrawWindow hwnd, ByVal 0, 0, RDW_FRAME Or RDW_INVALIDATE
    OnNCActivate = 1
End Function
Private Function OnNCCalcSize(ByVal hwnd As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Dim cs As NCCALCSIZE_PARAMS
    If wParam = 0 Then Exit Function
    CopyMemory cs, ByVal lParam, Len(cs)
    With cs.rgrc(0)
    .Left = .Left + SIZE_BORDER
    .Right = .Right - SIZE_BORDER
    .Bottom = .Bottom - SIZE_BORDER
    .Top = .Top + SIZE_CAPTION
    End With
    CopyMemory ByVal lParam, cs, Len(cs)
End Function
Private Sub UpdateButtons(ByVal hwnd As Long, ByVal pos As Long, Optional Button As Long = -1)
    Dim stat As Long, Btn() As Long, i As Long, msk() As Long, lst As Long, cst As Long, prs As Long, _
        cbtn As Long, b As Long, x As Long, y As Long, rc As RECT, iw As Long, hdc As Long, st As Long, _
        nstat As Long
    
    GetWindowRect hwnd, rc
    hdc = GetDCEx(hwnd, 0, DCX_WINDOW Or DCX_CLIPSIBLINGS)
    GetMem4 ByVal GetWindowLong(hwnd, GWL_USERDATA) + 34, stat
    GetButtons hwnd, Btn()
    prs = (GetKeyState(VK_LBUTTON) And &H8000&) \ &H8000&
    ReDim msk(3): msk(0) = 1
    For i = 1 To UBound(msk)
        msk(i) = (msk(i - 1)) * 4
    Next
    cst = prs + 1
    cbtn = GetBtnIndex(pos)
    For i = 0 To UBound(Btn)
        lst = stat \ msk(Btn(i))
        If Button = -1 Or (Button = Btn(i)) Then
            If (Btn(i) = cbtn And lst <> cst) Or (Btn(i) <> cbtn And lst <> 0) Then
                x = (rc.Right - rc.Left) - SIZE_BORDER
                y = 8 + BUT_SPACING + SIZE_BORDER
                b = 0
                Do
                    iw = picBut(Btn(b)).Width / 2540 * (1440 / Screen.TwipsPerPixelX)
                    x = x - iw - BUT_SPACING
                    b = b + 1
                Loop Until b > Btn(i)
                If (Btn(i) = cbtn And lst <> cst) Then
                    Select Case cst
                    Case 0: st = IIf(GetActiveWindow() = hwnd, 0, 3)
                    Case 1: st = IIf(GetActiveWindow() = hwnd, 2, 4)
                    Case 2: st = 1
                    End Select
                    lst = cst
                Else
                    lst = 0
                    st = IIf(GetActiveWindow() = hwnd, 0, 3)
                End If
                DrawStateButton hdc, x, y, Btn(i), st
            End If
        End If
        nstat = nstat Or (lst * msk(Btn(i)))
    Next
    nstat = nstat Or (stat And &HF00&)
    ReleaseDC hwnd, hdc
    GetMem4 nstat, ByVal GetWindowLong(hwnd, GWL_USERDATA) + 34
End Sub
Private Sub GetButtons(ByVal hwnd As Long, but() As Long)
    Dim sty As Long, esty As Long, i As Long
    
    ReDim but(3)
    but(i) = BUT_CLOSE: i = i + 1
 
    sty = GetWindowLong(hwnd, GWL_STYLE)
    esty = GetWindowLong(hwnd, GWL_EXSTYLE)
    
    If sty And WS_MAXIMIZEBOX Then but(i) = BUT_MAX: i = i + 1
    If sty And WS_MINIMIZEBOX Then but(i) = BUT_MIN: i = i + 1
    If esty And WS_EX_CONTEXTHELP Then but(i) = BUT_HELP: i = i + 1
    
    ReDim Preserve but(i - 1)
End Sub
Private Function GetBtnState(ByVal hwnd As Long, ByVal BtnIndex As Long) As Long
    Dim stat As Long, m As Long, i As Long
    GetMem4 ByVal GetWindowLong(hwnd, GWL_USERDATA) + 34, stat
    m = 1
    For i = 0 To BtnIndex: m = m * 4: Next
    stat = (stat \ m) And 3
End Function
Private Function GetBtnIndex(ByVal pos As Long) As Long
    Select Case pos
    Case HTCLOSE: GetBtnIndex = BUT_CLOSE
    Case HTMAXBUTTON:  GetBtnIndex = BUT_MAX
    Case HTMINBUTTON:  GetBtnIndex = BUT_MIN
    Case HTHELP:  GetBtnIndex = BUT_HELP
    Case Else: GetBtnIndex = -1
    End Select
End Function
Private Function GetBtnAreaWidth(ByVal hwnd As Long) As Long
    Dim Btn() As Long, i As Long
    GetButtons hwnd, Btn()
    For i = 0 To UBound(Btn)
        GetBtnAreaWidth = GetBtnAreaWidth + picBut(Btn(i)).Width / 2540 * (1440 / Screen.TwipsPerPixelX) + BUT_SPACING
    Next
End Function
Private Sub DrawBevel(ByVal hdc As Long, bmp As StdPicture, ByVal x As Long, ByVal y As Long, _
                      ByVal w As Long, ByVal h As Long, ByVal l As Long, ByVal t As Long, _
                      ByVal r As Long, ByVal b As Long)
    Dim obmp As Long, iw As Long, ih As Long, X1 As Long, Y1 As Long
    
    iw = bmp.Width / 2540 * (1440 / Screen.TwipsPerPixelX)
    ih = bmp.Height / 2540 * (1440 / Screen.TwipsPerPixelY)
    X1 = iw - r: Y1 = ih - b
    
    obmp = SelectObject(bufDC, bmp.Handle)
    
    BitBlt buf2DC, x, y, l, t, bufDC, 0, 0, vbSrcCopy
    StretchBlt buf2DC, x + l, y, w - l - r, t, bufDC, l, 0, iw - l - r, t, vbSrcCopy
    BitBlt buf2DC, x + w - r, y, r, t, bufDC, X1, 0, vbSrcCopy
    StretchBlt hdc, x, y + t, l, h - t - b, bufDC, 0, t, l, ih - t - b, vbSrcCopy
    StretchBlt hdc, x + w - r, y + t, r, h - t - b, bufDC, X1, t, r, ih - t - b, vbSrcCopy
    BitBlt hdc, x, y + h - b, l, b, bufDC, 0, Y1, vbSrcCopy
    StretchBlt hdc, x + l, y + h - b, w - l - r, b, bufDC, l, Y1, iw - l - r, b, vbSrcCopy
    BitBlt hdc, x + w - r, y + h - b, r, b, bufDC, X1, Y1, vbSrcCopy
    SelectObject bufDC, obmp
End Sub
Private Sub DrawStateButton(ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByVal Button As Long, ByVal State As Long)
    Dim iw As Long, ih As Long, bmp As StdPicture, obmp As Long
 
    Set bmp = picBut(Button)
    iw = bmp.Width / 2540 * (1440 / Screen.TwipsPerPixelX)
    ih = bmp.Height / 2540 * (1440 / Screen.TwipsPerPixelY) / 5
    obmp = SelectObject(bufDC, bmp.Handle)
    BitBlt hdc, x, y, iw, ih, bufDC, 0, ih * State, vbSrcCopy
    
    SelectObject bufDC, obmp
End Sub
Private Sub DrawProgress(ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByVal w As Long, _
                         ByVal bmp As StdPicture, ByVal State As Long, ByVal Value As Single, _
                         Optional ByVal bx As Long = 4)
    Dim iw As Long, ih As Long, sy As Long, obmp As Long, pw As Long
    
    iw = bmp.Width / 2540 * (1440 / Screen.TwipsPerPixelX)
    ih = bmp.Height / 2540 * (1440 / Screen.TwipsPerPixelY) / 4
    obmp = SelectObject(bufDC, bmp.Handle)
    Select Case State
    Case Taskbarlib.TBPFLAG.TBPF_NORMAL: sy = ih * 1
    Case Taskbarlib.TBPFLAG.TBPF_PAUSED: sy = ih * 2
    Case Taskbarlib.TBPFLAG.TBPF_ERROR: sy = ih * 3
    End Select
    pw = Value * w
    IntersectClipRect hdc, x, y, x + pw, y + ih
    BitBlt hdc, x, y, bx, ih, bufDC, 0, sy, vbSrcCopy
    StretchBlt hdc, x + bx, y, w - bx * 2, ih, bufDC, bx, sy, iw - bx * 2, ih, vbSrcCopy
    BitBlt hdc, x + w - bx, y, bx, ih, bufDC, iw - bx, sy, vbSrcCopy
    SelectClipRgn hdc, 0
    IntersectClipRect hdc, x + pw, y, x + w, y + ih
    BitBlt hdc, x, y, bx, ih, bufDC, 0, 0, vbSrcCopy
    StretchBlt hdc, x + bx, y, w - bx * 2, ih, bufDC, bx, 0, iw - bx * 2, ih, vbSrcCopy
    BitBlt hdc, x + w - bx, y, bx, ih, bufDC, iw - bx, 0, vbSrcCopy
    SelectClipRgn hdc, 0
    SelectObject bufDC, obmp
End Sub
Private Sub InvalidateProgress(ByVal hwnd As Long)
    Dim bwa As Long, rc As RECT
    bwa = GetBtnAreaWidth(hwnd)
    GetWindowRect hwnd, rc
    SetRect rc, SIZE_ICON + SIZE_BORDER, -SIZE_CAPTION, rc.Right - rc.Left - bwa - SIZE_BORDER * 2, 0
    RedrawWindow hwnd, rc, 0, RDW_FRAME Or RDW_INVALIDATE ' Or RDW_UPDATENOW
End Sub
Private Sub myDrawIcon(ByVal hwnd As Long, ByVal hdc As Long)
    Dim wi As WndExtInfo, hIcon As Long, iw As Long, ih As Single, ct As Long, x As Long, y As Long, a As Single, d As Single, _
        obmp As Long, pic As StdPicture, icn As StdPicture, rw As Long, rh As Long
    GetExtInfo hwnd, wi
    If wi.Icon.Sequence = 0 Then
        hIcon = SendMessage(hwnd, WM_GETICON, ICON_BIG, ByVal 0)
        DrawIconEx hdc, SIZE_BORDER + 2, 2, hIcon, SIZE_ICON - 4, SIZE_ICON - 4, 0, 0, 3
    Else
        ct = wi.Icon.NumOfFrame
        vbaObjSet icn, ByVal wi.Icon.Sequence
        If ct <= 0 Then ct = 1
        rw = icn.Width / 2540 * (1440 / Screen.TwipsPerPixelX)
        rh = icn.Height / 2540 * (1440 / Screen.TwipsPerPixelY) / ct
        a = rw / rh
        If a > 1 Then
            If rw > SIZE_ICON - 4 Then d = (SIZE_ICON - 4) / rw Else d = 1
        Else: If rh > SIZE_ICON - 4 Then d = (SIZE_ICON - 4) / rh Else d = 1
        End If
        iw = rw * d
        ih = rh * d
        x = ((SIZE_ICON - 4) - iw) \ 2 + SIZE_BORDER + 2
        y = ((SIZE_CAPTION - 4) - ih) \ 2 + 2
        If GetActiveWindow() = hwnd Then Set pic = picWnd.Active Else Set pic = picWnd.Inactive
        Debug.Print x, y, rw, rh
        obmp = SelectObject(bufDC, pic.Handle)
        BitBlt hdc, SIZE_BORDER, 0, SIZE_ICON, SIZE_CAPTION, bufDC, SIZE_BORDER, 0, vbSrcCopy
        SelectObject bufDC, icn.Handle
        AlphaBlend hdc, x, y, iw, ih, bufDC, 0, rh * wi.Icon.CurFrame, rw, rh, AB_32Bpp255
        SelectObject bufDC, obmp
        GetMem4 0, icn
    End If
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
Option Explicit
 
' Тестовая форма модуля пользовательской отрисовки окна
' © Кривоус Анатолий Анатольевич (The trick), 2014
 
Dim Value As Single
 
Private Sub cboIcon_Click()
    Select Case cboIcon.ListIndex
    Case 0: SetIcon Me, LoadResPicture("TRICKICON", vbResBitmap), 21
    Case 1: SetIcon Me, LoadResPicture("WAITICON", vbResBitmap), 20
    End Select
End Sub
 
Private Sub cmdDuplicate_Click()
    Dim frm As frmTest
    Set frm = New frmTest
    frm.Show
End Sub
 
Private Sub cmdHideProgress_Click()
    SetProgressState Me, TBPF_NOPROGRESS
End Sub
 
Private Sub cmdIcon_Click()
    PlayAnimation Me, 32, False
End Sub
Private Sub cmdIconLoop_Click()
    PlayAnimation Me, 32, True
End Sub
Private Sub cmdProgress_Click()
    tmrTimer.Enabled = True
    Value = 0
End Sub
Private Sub cmdShowProgress_Click()
    If optState(0).Value Then SetProgressState Me, TBPF_NORMAL
    If optState(1).Value Then SetProgressState Me, TBPF_PAUSED
    If optState(2).Value Then SetProgressState Me, TBPF_ERROR
End Sub
Private Sub cmdStopAnimation_Click()
    StopAnimation Me
End Sub
Private Sub cmdStopProgress_Click()
    tmrTimer.Enabled = False
End Sub
Private Sub Form_Load()
    SetNCSkin Me
    cboIcon.ListIndex = 0
End Sub
Private Sub Form_Unload(Cancel As Integer)
    RemoveNCSkin Me
End Sub
Private Sub optState_Click(Index As Integer)
    Call cmdShowProgress_Click
End Sub
 
Private Sub tmrTimer_Timer()
    Value = Value + 0.01
    SetProgressValue Me, Value
End Sub
Миниатюры
Нажмите на изображение для увеличения
Название: Безымянный.png
Просмотров: 936
Размер:	69.9 Кб
ID:	2141  
Вложения
Тип файла: rar UserDrawByTheTrick.rar (155.9 Кб, 17402 просмотров)
Метки basic, vb, win32
Размещено в Без категории
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 2
Комментарии
  1. Старый комментарий
    Аватар для Антихакер32
    Очень интересное, интересное и полезное решение,
    насыщенное многочисленными трюками, о существовании которых, я даже не помышлял, обязательно включу в свои
    шаблоны, мега-проекта "генератора программ"
    всё это не останется без моего внимания
    Запись от Антихакер32 размещена 05.03.2014 в 08:52 Антихакер32 вне форума
  2. Старый комментарий
    Аватар для Антихакер32
    Подключил через References необходимые компоненты,
    запустил, вроде-бы всё работает, только на панели задач
    у меня прогресс не отображается (у меня XP), ну это мелочи по сравнению с другим функционалом
    Запись от Антихакер32 размещена 06.03.2014 в 01:26 Антихакер32 вне форума
 
Новые блоги и статьи
Был там один разговор по поводу свободы в материальном мире.
kumehtar 19.08.2026
Суть: рассматривается живое существо, оказавшееся внутри довольно странной системы (этого мира) и пытающееся обустроить в ней свой кусок пространства. Жизнь действительно предъявляет каждому. . .
Когда логика программы не спасает от человеческих ошибок
Maks 18.08.2026
В последнее время всё чаще и чаще сталкиваюсь с таким явлением, как абсолютная невнимательность (или глупость) пользователей. Проявляется это чаще всего на работе в коллективе. Допустим, человек с. . .
Лето уходит
kumehtar 17.08.2026
Мысли в слух
kumehtar 17.08.2026
Забавно, насколько сейчас стала доступна информация. Например о магии, духовном развитии, медитациях, и других подобных направлениях, ранее зачастую тайных, передаваемых от учителя к ученику. Хотя. . .
Перемещение строк из ТЧ в другой документ с учетом текущего пробега
Maks 17.08.2026
Реализация из решения ниже выполнена на примере нетипового документа "Автозапчасти", с ТЧ "Шины". За основу взят алгоритм отсюда: https:/ / www. cyberforum. ru/ blogs/ 359708/ 10838. html Задача: . . .
Саморегулирующийся социальный контракт для сервера cross-section.
Hrethgir 14.08.2026
С кодом конечно таких глубоких размышлений пока не было, впрочем я уже привык к алгоритмизации. Суть предмета записи: снова в диалоге с нейросетью (я взял пока себе ник для учётки админа - Rector). . . .
Часы электронные
Uhbif79 12.08.2026
Выкладываю программу часов. Программа позволяет: 1. Использовать системное время и дату, 2. Есть возможность вводить время и дату вручную. 3. Реализованы 2 будильника: начало и конец рабочего дня. . . .
Часы с будильником на основе класса QLCDNumber
Uhbif79 12.08.2026
Всем добрый день, выкладываю программу часов с будильником на основе класса QLCDNumber. Здесь я пробовал самостоятельно создавал классы, впервые столкнулся с видимостью переменной одного класса из. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru