Доброго всем времени. Пытаюсь создать меню. Проблема в моментах прорисовки...Для начала код.
Модуль:
Option Explicit
Public Const SWP_NOMOVE = &H2
Public Const SWP_NOSIZE = &H1
Public Const WM_LBUTTONDOWN = &H201
Private Type POINTAPI
X As Long
Y As Long
End Type
Public Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Private Type CBTACTIVATESTRUCT
fMouse As Long
hWndActive As Long
End Type
Public ParentHwnd As Long
Public ContHwnd As Long
Public hHook As Long
Dim CBT As CBTACTIVATESTRUCT
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (lpDest As Any, lpSource As Any, ByVal cBytes As Long)
Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
Private Declare Function WindowFromPoint Lib "user32" (ByVal xPoint As Long, ByVal yPoint As Long) As Long
Private Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, ByVal nCode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function ScreenToClient Lib "user32" (ByVal hWnd As Long, lpPoint As POINTAPI) As Long
Public Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long
Public Declare Function GetWindowRect Lib "user32" (ByVal hWnd As Long, lpRect As RECT) As Long
Public Declare Function SetParent Lib "user32" (ByVal hWndChild As Long, ByVal hWndNewParent As Long) As Long
Public 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
Public Function HookProc(ByVal nCode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Dim lngHandle As Long
Dim lpPoint As POINTAPI
CopyMemory CBT, ByVal lParam, Len(CBT)
Select Case CBT.fMouse
Case WM_LBUTTONDOWN
Call GetCursorPos(lpPoint)
lngHandle = WindowFromPoint(lpPoint.X, lpPoint.Y)
If lngHandle <> ContHwnd Then Call HideContainer
End Select
HookProc = CallNextHookEx(hHook, nCode, wParam, lParam)
End Function
Sub HideContainer()
Dim rc As RECT
Dim p As POINTAPI
GetWindowRect ContHwnd, rc
p.X = rc.Left: p.Y = rc.Top
ScreenToClient ParentHwnd, p
SetParent ContHwnd, ParentHwnd
MoveWindow ContHwnd, p.X, p.Y, rc.Right - rc.Left, 20, True
Call UnhookWindowsHookEx(hHook)
End Sub
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 SetWindowPos Lib "user32" (ByVal hWnd As Long, ByVal hWndInsertAfter As Long, ByVal X As Long, ByVal Y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
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 GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long
'Private Declare Function InvalidateRect Lib "user32" (ByVal hWnd As Long, ByVal lpRect As Long, ByVal bErase As Long) As Long
Private Sub OpenContainer()
Dim rc As RECT
ContHwnd = hWnd
ParentHwnd = Parent.hWnd
If ScaleHeight = 20 Then
GetWindowRect hWnd, rc
SetParent hWnd, 0
MoveWindow hWnd, rc.Left, rc.Top, ScaleWidth, 100, True
SetWindowPos hWnd, -1, rc.Left, rc.Top, 0, 0, SWP_NOMOVE Or SWP_NOSIZE
hHook = SetWindowsHookEx(WH_JOURNALRECORD, AddressOf HookProc, 0, 0)
Else
Call HideContainer
End If
End Sub
Private Sub UserControl_Click()
OpenContainer
End Sub
Private Sub UserControl_Initialize()
SetWindowLong hWnd, GWL_EXSTYLE, WS_EX_TOOLWINDOW Or GetWindowLong(hWnd, GWL_EXSTYLE)
End Sub
'Private Sub UserControl_Paint()
' Line (0, 0)-(ScaleWidth, 0)
' If Ambient.UserMode = False Then Exit Sub
' InvalidateRect hWnd, 0, False
'End Sub
Private Sub UserControl_Resize()
Width = 100 * Screen.TwipsPerPixelX
Height = 20 * Screen.TwipsPerPixelY
End Sub
Private Sub UserControl_Terminate()
Call UnhookWindowsHookEx(hHook)
End Sub
Проблемы следующие:
Если ставить свойство контрола Autoredraw=false, то линия "моргает", если Autoredraw=true, то тогда "моргает" контрол. А при нажатии на заголовок формы вообще исчезает на некоторое время.
Line привёл для примера. Впоследствии собираюсь пользоваться FillRect'ом...
В коде у меня закомментирована эта процедура. Если использовать InvalidateRect или RedrawWindow, тогда Line "моргает". В противном случае, "моргает" контрол
Если это вопрос, то нет, не должна. Итогом должен быть таким: ни контрол, ни то, что "лежит" на контроле моргать не должно. Добиться того, чтобы не "моргал" контрол, у меня получается в случае, если свойство контрола Autoredraw = False и в процедуре UserControl_Paint прописано InvalidateRect. Но тогда на контроле ничего не нарисуешь, не зальёшь FillRect'ом....
InvalidateRect hWnd, 0, False при последнем параметре false не должна обновлять фон.
Только, если мне не изменяет память, прорисовка идет в парах BeginPaint … EndPaint, которые вызываются после InvalidateRect.
То есть импортируй эти функции, и вызови после InvalidateRect.
Если контрол не трогать, то прорисовка идёт. Если вызывать OpenContainer - начинается "моргание". И при "открытом" контроле при нажатии на заголовок формы, контрол исчезает на некоторое время.
Вопрос в том в какой очередности и с какой частотой он их сообщает. Время выполнения API неопределенно.
Логика сейчас.
Если 20 -> Открываем. В любом другом случае(100), закрываем.
Т.е. закрытие может быть вызвано в процессе открытия. А потом опять вызвано открытие.
Или несколько раз вызвано открытие/закрытие(Такое тоже может быть).
Нужно.
1. Открываем. Если закрыто(флаг или возвращаемое API значение, например hHook) и UserControl_Click.
3. Закрываем. Наоборот – если открыто и UserControl_Click.
3. (Желательно) Если открываем (в процессе), то не закрываем и не открываем повторно. Если закрываем(в процессе) то не открываем и не закрываем повторно.
Да, не стало...и предложенный вариант тоже также глючит. Пробовал хукать контрол - моргание исчезло, но при нажатии на заголовок формы срабатывает событие Usercontrol_MouseDown. Плюс на контроле будет таймер и с ним тоже проблемы, но об этом не сейчас...
Согласен. Но для перемещения предмета с места на место не важен язык программирования. Не сложно изучить синтаксис другого языка, сложнее решить поставленную задачу.