BalloonMsg::BalloonMsg(CWnd* wnd, const TCHAR* title, const TCHAR* msg, MsgIcon icon, CPoint pos) { if (wnd == 0) { ASSERT(false); delete this; return; } ASSERT(msg && title); if (!wnd->IsWindowVisible()) // it only makes sense to display balloon for visible windows { MessageBox(msg, title); delete this; return; } closing_ = false; Create(0, WS_POPUP | TTS_NOPREFIX | TTS_BALLOON | TTS_ALWAYSTIP); if (m_hWnd == 0) return; msg_ = msg; title_ = title; const TCHAR* text= msg_; struct OLDTOOLINFO { UINT cbSize; UINT uFlags; HWND hwnd; UINT uId; RECT rect; HINSTANCE hinst; LPTSTR lpszText; } ti; // new TOOLINFO with extra reserved field changes the way balloons work rendering them useless... // TOOLINFO ti; ti.cbSize = sizeof ti; ti.uFlags = TTF_TRACK | TTF_IDISHWND; ti.hwnd = wnd->m_hWnd; ti.uId = 1; ti.hinst = NULL; ti.lpszText = const_cast<TCHAR*>(text); //LPSTR_TEXTCALLBACK; ti.rect.left = 0; ti.rect.top = 0; ti.rect.right = 0; ti.rect.bottom = 0; // ti.lParam = 0; SendMessage(TTM_ADDTOOL, 0, LPARAM(&ti)); SetMaxTipWidth(300); // SetTitle(icon, title_); const TCHAR* ttl= title_; SendMessage(TTM_SETTITLE, icon, LPARAM(ttl)); if (pos.x == 0 && pos.y == 0) { CRect rect; wnd->GetWindowRect(rect); pos = rect.CenterPoint(); } SendMessage(TTM_TRACKPOSITION, 0, MAKELONG(pos.x, pos.y)); SendMessage(TTM_TRACKACTIVATE, true, LPARAM(&ti)); ::MessageBeep(MB_OK); SetTimer(TIMER_ID, 10000, 0); wnd->SetFocus(); SubclassWnd(*wnd); InstallMouseHook(); }
LRESULT MainDialogProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam) { HKL hKl; switch (Msg) { case WM_INITDIALOG: { WCHAR Buf[255]; UpdateData(hDlg); hMainDlg = hDlg; SubclassWnd(GetDlgItem(hDlg, IDC_LIST), L"List"); SubclassWnd(GetDlgItem(hDlg, IDC_EDIT1), L"Edit1"); SubclassWnd(GetDlgItem(hDlg, IDC_KLID), L"Klid"); SubclassWnd(GetDlgItem(hDlg, ID_CANCEL), L"CancelB"); SubclassWnd(GetDlgItem(hDlg, IDC_ACTIVATE), L"ActivateB"); SubclassWnd(GetDlgItem(hDlg, IDC_REFRESH), L"RefreshB"); SubclassWnd(GetDlgItem(hDlg, IDC_UNLOAD), L"UnloadB"); SubclassWnd(GetDlgItem(hDlg, IDC_LOAD), L"LoadB"); CheckRadioButton(hDlg, IDC_FROMLIST, IDC_FROMEDIT, IDC_FROMLIST); SetWindowText(GetDlgItem(hDlg, IDC_KLID), L"00000419"); swprintf(Buf, L"Current thread id: %d", GetCurrentThreadId()); SetWindowText(GetDlgItem(hDlg, IDC_CURTHREAD), Buf); SetWindowText(GetDlgItem(hDlg, IDC_DELAY), L"0"); return 0; } /* WM_INITDIALOG */ case WM_COMMAND: { switch(LOWORD(wParam)) { case ID_CANCEL: { EndDialog(hDlg, ERROR_CANCELLED); break; } case IDC_ACTIVATE: { if((hKl = GetActivateHandle(hDlg)) != INVALID_HANDLE_VALUE) { Sleep(GetDelayMilliseconds(hDlg)); if(!(hKl = ActivateKeyboardLayout(hKl, GetActivateFlags(hDlg)))) FormatBox(hDlg, MB_ICONERROR, L"Error", L"ActivateKeyboardLayout() failed. %d", GetLastError()); else UpdateData(hDlg); //FormatBox(hDlg, 0, L"Activated", L"Prev - %x, err - %d.", hKl, // GetLastError()); } else MessageBox(hDlg, L"No item selected", L"Error", MB_ICONERROR); break; } case IDC_UNLOAD: { if((hKl = GetSelectedLayout(hDlg)) != INVALID_HANDLE_VALUE) { Sleep(GetDelayMilliseconds(hDlg)); if(!UnloadKeyboardLayout(hKl)) FormatBox(hDlg, MB_ICONERROR, L"Error", L"UnloadKeyboardLayout() failed. %d", GetLastError()); else UpdateData(hDlg); } else MessageBox(hDlg, L"No item selected", L"Error", MB_ICONERROR); break; } case IDC_LOAD: { WCHAR buf[255]; GetWindowText(GetDlgItem(hDlg, IDC_KLID), buf, sizeof(buf)); Sleep(GetDelayMilliseconds(hDlg)); if(!LoadKeyboardLayout(buf, GetLoadFlags(hDlg))) FormatBox(hDlg, MB_ICONERROR, L"Error", L"LoadKeyboardLayout() failed. %d", GetLastError()); else UpdateData(hDlg); break; } case IDC_REFRESH: { UpdateData(hDlg); break; } case IDC_NEWTHREAD: { if(!CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL)) { FormatBox(hDlg, MB_ICONERROR, L"Error!", L"Can not create thread (%d).", GetLastError()); } } case IDC_LIST: { if(HIWORD(wParam) == LBN_SELCHANGE) { WCHAR buf[25]; if((hKl = GetSelectedLayout(hDlg)) != NULL) { swprintf(buf, L"%x", hKl); SetWindowText(GetDlgItem(hDlg, IDC_HANDLE), buf); } } break; } } return TRUE; } /* WM_COMMAND */ case WM_INPUTLANGCHANGE: { FormatMsg(L"dlg WM_INPUTLANGCHANGE lParam=%x wParam=%x\n", lParam, wParam); return FALSE; } case WM_INPUTLANGCHANGEREQUEST: { FormatMsg(L"dlg WM_INPUTLANGCHANGEREQUEST lParam=%x wParam=%x\n", lParam, wParam); UpdateData(hDlg); return FALSE; } case WM_CLOSE: { EndDialog(hDlg, ERROR_CANCELLED); return TRUE; } /* WM_CLOSE */ default: return FALSE; } }