Не завершается приложение при удалении класса окна

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
viter.alex
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 221
Зарегистрирован: 27.07.2008 (Вс) 20:17
Откуда: Montreal

Не завершается приложение при удалении класса окна

Сообщение viter.alex » 08.07.2009 (Ср) 2:32

Создаю свое окно, все хорошо: создается, сообщения обрабатываются, но почему-то не завершается программа при удалении класса. Сейчас в коде стоит UnregisterClass, но я пробовал и DestroyWindow. Делаю это в первый раз, поэтому буду рад любым конструктивным замечаниям.
Код первого модуля
Код: Выделить всё
'Регистрация клавиш на приложение
Public Declare Function RegisterHotKey Lib "user32" (ByVal hwnd As Long, ByVal id As Long, ByVal fsModifiers As Long, ByVal vk As Long) As Long
Public Declare Function UnregisterHotKey Lib "user32" (ByVal hwnd As Long, ByVal id As Long) As Long

Public Const MOD_WIN = &H8

'Описание класса окна
Public Declare Function LoadIcon Lib "user32" Alias "LoadIconA" (ByVal hInstance As Long, ByVal lpIconName As String) As Long
Public Declare Function LoadCursor Lib "user32" Alias "LoadCursorA" (ByVal hInstance As Long, ByVal lpCursorName As String) As Long
Public Declare Function GetStockObject Lib "gdi32" (ByVal nIndex As Long) As Long

Public Const CS_HREDRAW = &H2
Public Const CS_VREDRAW = &H1
Public Const IDI_APPLICATION = 32512&
Public Const IDC_ARROW = 32512&
Public Const WHITE_BRUSH = 0

'Регистрация класса
Public Declare Function RegisterClass Lib "user32" Alias "RegisterClassA" (Class As WNDCLASS) As Long

Public Type WNDCLASS
    style As Long
    lpfnwndproc As Long
    cbClsextra As Long
    cbWndExtra2 As Long
    hInstance As Long
    hIcon As Long
    hCursor As Long
    hbrBackground As Long
    lpszMenuName As String
    lpszClassName As String
End Type

'Создание окна
Public Declare Function CreateWindowEx Lib "user32" Alias "CreateWindowExA" (ByVal dwExStyle As Long, ByVal lpClassName As String, ByVal lpWindowName As String, ByVal dwStyle As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hWndParent As Long, ByVal hMenu As Long, ByVal hInstance As Long, lpParam As Any) As Long

Public Const WS_POPUP = &H80000000

'Обработка сообщений окна
Public Declare Function GetMessage Lib "user32" Alias "GetMessageA" (lpMsg As MSG, ByVal hwnd As Long, ByVal wMsgFilterMin As Long, ByVal wMsgFilterMax As Long) As Long
Public Declare Function DispatchMessage Lib "user32" Alias "DispatchMessageA" (lpMsg As MSG) As Long

'Обработка сообщений окна по умолчанию
Public Declare Function DefWindowProc Lib "user32" Alias "DefWindowProcA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

'Удаление зарегистированного класса
Public Declare Function UnregisterClass Lib "user32" Alias "UnregisterClassA" (ByVal lpClassName As String, ByVal hInstance As Long) As Long

'Сообщение
Public Declare Function MessageBox Lib "user32" Alias "MessageBoxA" (ByVal hwnd As Long, ByVal lpText As String, ByVal lpCaption As String, ByVal wType As Long) As Long

Public Const MB_OK = &H0&

Public Type MSG
    hwnd As Long
    message As Long
    wParam As Long
    lParam As Long
    time As Long
    pt As POINTAPI
End Type

Public hWndSpecChar As Long
Public Const CLSNAME = "ClsSpecChar"
Public Const APPNAME = "SpecChar"

Sub Main()
  Dim WndCl As WNDCLASS
  Dim wMsg As MSG
  Dim adr As Long
  'Описываю класс
  With WndCl
    .style = CS_HREDRAW Or CS_VREDRAW
    .lpfnwndproc = GetAddress(AddressOf SpecCharWndProc)
    .cbClsextra = 0&
    .cbWndExtra2 = 0&
    .hInstance = App.hInstance
    .hIcon = LoadIcon(0&, IDI_APPLICATION)
    .hCursor = LoadCursor(0, IDC_ARROW)
    .hbrBackground = GetStockObject(WHITE_BRUSH)
    .lpszMenuName = vbNullString
    .lpszClassName = CLSNAME
  End With
  'Регистрирую его
  If RegisterClass(WndCl) = 0 Then _
    MessageBox 0&, "Не удается зарегистировать класс " & CLSNAME & "!", APPNAME & " Ошибка", MB_OK: _
    Exit Sub
  'Создаю окно
  hWndSpecChar = CreateWindowEx(0&, CLSNAME, "", WS_POPUP, 0, 0, 0, 0, 0, 0, WndCl.hInstance, vbNullString)
  'Регистрирую на себя сочетания клавиш
  RegisterHotKey hWndSpecChar, &HBFFF, MOD_WIN, vbKeyT 'Win+T
  RegisterHotKey hWndSpecChar, &HC000, MOD_WIN, vbKeyG 'Win+G
  RegisterHotKey hWndSpecChar, &HC001, MOD_WIN, vbKeyJ 'Win+J
  'Обрабатываю сообщения, пока не получу сообщение о выходе
  Do While GetMessage(wMsg, 0&, 0&, 0&)
    DispatchMessage wMsg
  Loop
  'Удаляю зарегистрированные клавиши
  UnregisterHotKey hWndSpecChar, &HBFFF
  UnregisterHotKey hWndSpecChar, &HC000
  UnregisterHotKey hWndSpecChar, &HC001
  'Удаляю класс
  UnregisterClass CLSNAME, App.hInstance
End Sub

Public Function GetAddress(ByVal lngAddr As Long) As Long
  GetAddress = lngAddr
End Function


Обрабатываю сообщения окна:
Код второго модуля
Код: Выделить всё
Option Explicit

'Сообщения в окно
Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long

Public Const WM_HOTKEY = &H312
Public Const WM_CLOSE = &H10
Public Const WM_QUIT = &H12
Public Const WM_COMMAND = &H111

'Работа с курсором
Public Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
Public Declare Function GetCaretPos Lib "user32" (lpPoint As POINTAPI) As Long
Public Declare Function WindowFromPoint Lib "user32" (ByVal xPoint As Long, ByVal yPoint As Long) As Long
Public Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Public Declare Function GetFocus Lib "user32" () As Long
Public Declare Function GetClientRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
Public Declare Function ClientToScreen Lib "user32" (ByVal hwnd As Long, lpPoint As POINTAPI) As Long

Public CursorPos As POINTAPI
Public CaretPos As POINTAPI

Public Type RECT
        Left As Long
        Top As Long
        Right As Long
        Bottom As Long
End Type

Public Type POINTAPI
        x As Long
        y As Long
End Type

'Работа с меню
Public Declare Function CreatePopupMenu Lib "user32" () As Long
Public Declare Function AppendMenu Lib "user32" Alias "AppendMenuA" (ByVal hMenu As Long, ByVal wFlags As Long, ByVal wIDNewItem As Long, ByVal lpNewItem As Any) As Long
Public Declare Function DestroyMenu Lib "user32" (ByVal hMenu As Long) As Long
Public Declare Function TrackPopupMenu Lib "user32" (ByVal hMenu As Long, ByVal wFlags As Long, ByVal x As Long, ByVal y As Long, ByVal nReserved As Long, ByVal hwnd As Long, lprc As Any) As Long

Public Const MF_ENABLED = &H0&
Public Const MF_GRAYED = &H1&
Public Const TPM_RIGHTALIGN = &H8&

Public hPopMenu As Long

'-------------
Dim hFcsWnd As Long, rectFrgWnd As RECT, rectWinPoint As POINTAPI
Dim hWndBk As Long, sWndBkName As String * 50
Dim hDC As Long


Public Function SpecCharWndProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
  Static i As Long

  Select Case uMsg
    Case WM_HOTKEY 'Если нажали горячую клавишу
      Select Case wParam 'Какую горячую клавишу нажали
        Case &HBFFF 'Win+T
          Dim j As Integer
          hPopMenu = CreatePopupMenu
          'Заполняем меню. Четные неактивны, нечетные активны.
          For j = 1 To 10
            AppendMenu hPopMenu, IIf(j Mod 2 <> 0, MF_ENABLED, MF_GRAYED), CLng(j), CStr(j)
          Next j

          Call GetCaretPos(CaretPos) 'Позиция курсора ввода текста
          hFcsWnd = GetFocus 'Окно, в котором работает пользователь
          GetClientRect hFcsWnd, rectFrgWnd 'Координаты активного окна
          rectWinPoint.y = rectFrgWnd.Top
          rectWinPoint.x = rectFrgWnd.Left
          ClientToScreen hFcsWnd, rectWinPoint 'Координаты активного окна в экранных координатах
          i = i + 1
          Debug.Print i & " Win+T" & vbTab & "X:" & CaretPos.x & " Y:" & CaretPos.y
          'Показываем меню
          TrackPopupMenu hPopMenu, &H0, rectWinPoint.x + CaretPos.x, rectWinPoint.y + CaretPos.y, 0, hWndSpecChar, 0
          DestroyMenu hPopMenu
        Case &HC000 'Win+G
          i = i + 1
          Call GetCursorPos(CursorPos) 'Позиция курсора мыши
          hWndBk = WindowFromPoint(CursorPos.x, CursorPos.y)
          Call GetWindowText(hWndBk, sWndBkName, 50)
          Debug.Print i & " Курсор мыши находится в точке X=" & CursorPos.x & "; Y=" & CursorPos.y & ". Над окном " & sWndBkName & vbCr & _
                      "Курсор ввода находится в точке X = " & CaretPos.x & "; Y = " & CaretPos.y
        Case &HC001 'Win+J
          Debug.Print "Выход из программы…"
          Call SendMessage(hWndSpecChar, WM_CLOSE, 0, 0)
      End Select
    Case WM_COMMAND
      If wParam >= &H1 And wParam <= &H10 Then
        Debug.Print "wParam = &H" & Hex(wParam) & "; lParam = &H" & Hex(lParam)
      End If
  End Select
  SpecCharWndProc = DefWindowProc(hwnd, uMsg, wParam, lParam)
End Function
Лучше день потерять — потом за пять минут долететь!

BV
Thinker
Thinker
Аватара пользователя
 
Сообщения: 3987
Зарегистрирован: 12.09.2004 (Вс) 0:55
Откуда: Молдавия, г. Кишинёв

Re: Не завершается приложение при удалении класса окна

Сообщение BV » 08.07.2009 (Ср) 9:11

На WM_DESTROY добавь PostQuitMessage(_код_), и убери UnregisterClass, оно там совершенно не нужно
const char *out = "|*0>78-,+<|"; size_t cc = char_traits<char>::length(out);
for (size_t i=0;i<cc;i++){cout<<static_cast<char>((out[i]^89));}cout<<endl;

viter.alex
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 221
Зарегистрирован: 27.07.2008 (Вс) 20:17
Откуда: Montreal

Re: Не завершается приложение при удалении класса окна

Сообщение viter.alex » 08.07.2009 (Ср) 14:24

Добавил, но все равно не завершается.
Код: Выделить всё
    Case WM_DESTROY
      PostQuitMessage nExitCode
    Case WM_QUIT
      nExitCode = wParam
Лучше день потерять — потом за пять минут долететь!

viter.alex
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 221
Зарегистрирован: 27.07.2008 (Вс) 20:17
Откуда: Montreal

Re: Не завершается приложение при удалении класса окна

Сообщение viter.alex » 10.07.2009 (Пт) 20:00

Все получилось. Обработчик на WM_DESTROY поставил, а послать его забыл :oops:
Лучше день потерять — потом за пять минут долететь!


Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 98

    TopList