/*++ Copyright (c) 2001, Microsoft Corporation Module Name: uicomp.h Abstract: This file defines the UIComposition Class. Author: Revision History: Notes: --*/ #ifndef _UICOMP_H_ #define _UICOMP_H_ #include "imc.h" #include "polytext.h" #include "caret.h" #include "tls.h" #include "globals.h" #include "cuiwnd.h" #include "cuitb.h" #define WM_UICOMP_SETCURSOR (WM_USER + 1000) typedef enum { IME_UIWND_UNKNOWN = 0, IME_UIWND_LEVEL1 = 1, IME_UIWND_LEVEL2 = 2, IME_UIWND_LEVEL3 = 3, IME_UIWND_LEVEL1_OR_LEVEL2 = 4 } IME_UIWND_STATE; static const LONG DEFFRAME_LEFT_MARGIN = 2; static const LONG DEFFRAME_TOP_MARGIN = 3; static const LONG DEFFRAME_BOTTOM_MARGIN = 7; static const LONG DEFFRAME_TOP_STR_MARGIN = 7; static const LONG DEFFRAME_ENTER_BTN_CX = 18; static const LONG DEFFRAME_ENTER_BTN_CY = 18; static const LONG COMPBTN_LEFT_MARGIN = 1; static const LONG COMPBTN_TOP_MARGIN = 1; class CCompFrameWindow; class CDefCompFrameWindow; ////////////////////////////////////////////////////////////////////////////// // // CCompFinalizeButton // ////////////////////////////////////////////////////////////////////////////// class CCompFinalizeButton : public CUIFToolbarButton { public: CCompFinalizeButton(CCompFrameWindow *pCompFrameWindow, DWORD dwID, RECT *prc, DWORD dwStyle, DWORD dwSBtnStyle, DWORD dwSBtnShowType); ~CCompFinalizeButton(); virtual void OnLeftClick(); CCompFrameWindow *m_pCompFrameWnd; }; ////////////////////////////////////////////////////////////////////////////// // // CCompFrameWinodow // ////////////////////////////////////////////////////////////////////////////// class CCompFrameWindow : public CUIFWindow { public: CCompFrameWindow(HIMC hIMC, DWORD dwStyle) : CUIFWindow(::GetInstance(), dwStyle) { m_hIMC = hIMC; } HIMC GetIMC() {return m_hIMC;} private: HIMC m_hIMC; }; ////////////////////////////////////////////////////////////////////////////// // // CDefCompFrameFripper // ////////////////////////////////////////////////////////////////////////////// class CDefCompFrameGripper : public CUIFGripper { public: CDefCompFrameGripper::CDefCompFrameGripper(CDefCompFrameWindow *pDefCompFrameWnd, RECT *prc, DWORD dwStyle); CDefCompFrameWindow *m_pDefCompFrameWnd; }; ////////////////////////////////////////////////////////////////////////////// // // CDefCompFrameWinodow // ////////////////////////////////////////////////////////////////////////////// class CDefCompFrameWindow : public CCompFrameWindow { public: CDefCompFrameWindow(HIMC hIMC, DWORD dwStyle); virtual ~CDefCompFrameWindow(); virtual void HandleMouseMsg( UINT uMsg, POINT pt ); virtual BOOL OnSetCursor( UINT uMsg, POINT pt ); void Init(); void SetCompStrRect(int dx, int dy, BOOL fShow); virtual void OnCreate(HWND hWnd); virtual LRESULT OnWindowPosChanged(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); void SetCompStrWnd(HWND hwnd) {m_hwndCompStr = hwnd;} private: void SavePosition(); void LoadPosition(); int GetGripperWidth(); void MyScreenToClient(POINT *ppt, RECT *prc) { if (ppt) ScreenToClient(GetWnd(), ppt); if (prc) { ScreenToClient(GetWnd(), (POINT *)&prc->left); ScreenToClient(GetWnd(), (POINT *)&prc->right); } } HWND m_hwndCompStr; CDefCompFrameGripper *m_pGripper; CCompFinalizeButton *m_pEnterButton; MARGINS _marginsButton; }; ////////////////////////////////////////////////////////////////////////////// // // CCompButtonFrameWinodow // ////////////////////////////////////////////////////////////////////////////// class CCompButtonFrameWindow : public CCompFrameWindow { public: CCompButtonFrameWindow(HIMC hIMC, DWORD dwStyle); virtual ~CCompButtonFrameWindow(); void Init(); void OnCreate(HWND hWnd); void MoveShow(int x, int y, BOOL fShow); private: CCompFinalizeButton *m_pEnterButton; MARGINS _marginsButton; }; ////////////////////////////////////////////////////////////////////////////// // // UIComposition // ////////////////////////////////////////////////////////////////////////////// class UIComposition { public: static LRESULT CompWndProc(HWND hCompWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); public: UIComposition(HWND hUIWnd); virtual ~UIComposition(); public: HRESULT OnCreate(); HRESULT OnDestroy(); HRESULT OnImeSetContext(IMCLock& imc, HWND hUIWnd, BOOL fActivate, DWORD isc); HRESULT OnImeSetContextAfter(IMCLock& imc); HRESULT OnImeSelect(BOOL fSelect); HRESULT OnImeStartComposition(IMCLock& imc, HWND hUIWnd); HRESULT OnImeCompositionUpdate(IMCLock& imc); HRESULT OnImeCompositionUpdateByTimer(IMCLock& imc); HRESULT OnImeEndComposition(); HRESULT OnImeNotifySetCompositionWindow(IMCLock& imc); HRESULT OnImeNotifySetCompositionFont(IMCLock& imc); HRESULT OnPaint(TLS* ptls, HWND hCompWnd, HDC hDC, PAINTSTRUCT& ps, IMCLock& imc); HRESULT OnTimer(HWND hCompWnd); HRESULT OnSetCursor(IMCLock& imc, WPARAM wParam, LPARAM lParam); private: HRESULT CreateCompositionWindow(IMCLock& imc, HWND hUIWnd); HRESULT DestroyCompositionWindow(); HRESULT HideCompositionWindow(); HRESULT UpdateShowCompWndFlag(IMCLock& imc, DWORD* pdwCompStrLen); HRESULT UpdateCompositionRect(IMCLock& imc); HRESULT UpdateFont(IMCLock& imc); UINT CalcSingleTextExtentPoint(IMCLock& imc, HDC hDC, LPCWSTR lpsz, int string_len, PBYTE lpAttr, BOOL fCompAttr, CCompClauseStore *compclause, int window_width, LPSIZE real_size, CPolyText& poly_text, int row_index); UINT CalcMultiTextExtentPoint(IMCLock& imc, HDC hDC, LPCWSTR lpsz, int string_len, PBYTE lpAttr, BOOL fCompAttr, CCompClauseStore *compclause, int window_width, LPSIZE real_size, CPolyText& poly_text); HRESULT SetCaretPos(HDC hDC, CCaret& caret, int x, int y, LPCWSTR lpCompStr, DWORD string_length, DWORD cursor_pos, BOOL fVert, BOOL fEndCaret); HRESULT UpdateCaretRect(HDC hDC, int index, DWORD dwCursorPos, BOOL fVert, BOOL fEndCaret); typedef struct tagCOMPWND { HWND hCompWnd; CPolyText poly_text; CCaret caret; struct { LONG acpStart; LONG cch; } sel; void _ClientToScreen(RECT *prc) { ::ClientToScreen(hCompWnd, (POINT *)&prc->left); ::ClientToScreen(hCompWnd, (POINT *)&prc->right); } BOOL fDefaultCompWnd : 1; } COMPWND; HRESULT PolyTextAndAttrOut(TLS* ptls, HDC hDC, BOOL fVert, COMPWND* pcompwnd); HRESULT MakeSquiggleLine(POINT start_pt, POINT end_pt, int frequency, int amplitude, BOOL fVert, CArray& squiggle_line); // // Query IME UI Window state // public: static IME_UIWND_STATE InquireImeUIWndState(IMCLock& imc) { HWND hDefImeWnd; if (IsWindow(hDefImeWnd=ImmGetDefaultIMEWnd(NULL))) { // // Internal notification to UI window // When receive this msg in UI wnd, then return IME context flag. // return (IME_UIWND_STATE)SendMessage(hDefImeWnd, WM_IME_NOTIFY, IMN_PRIVATE_GETCONTEXTFLAG, 0); } return IME_UIWND_UNKNOWN; } typedef struct { LONG acpStart; LONG acpEnd; RECT *prc; BOOL *pfClipped; void SetICOARGS(ICOARGS *pArgs) { acpStart = pArgs->text_ext.acpStart; acpEnd = pArgs->text_ext.acpEnd; prc = pArgs->text_ext.prc; pfClipped = pArgs->text_ext.pfClipped; } } TEXTEXT; HRESULT OnPrivateGetTextExtent(IMCLock& imc, TEXTEXT *ptext_ext); static BOOL GetImeUIWndTextExtent(TEXTEXT *ptext_ext) { HWND hDefImeWnd; if (IsWindow(hDefImeWnd=ImmGetDefaultIMEWnd(NULL))) { // // Internal notification to UI window // When receive this msg in UI wnd, then return IME context flag. // return SendMessage(hDefImeWnd, WM_IME_NOTIFY, IMN_PRIVATE_GETTEXTEXT, (LPARAM)ptext_ext) ? TRUE : FALSE; } return FALSE; } public: HRESULT OnPrivateGetContextFlag(IMCLock& imc, BOOL fStartComposition, IME_UIWND_STATE* uists); HRESULT GetCompStrExtent(POINT pt, ULONG *puEdge, ULONG *puQuadrant, IMCLock& imc); // // Get candidate window rectangle from composition window // public: typedef struct tagCandRectFromComposition { LANGID langid; DWORD dwCharPos; RECT* out_rcArea; } CandRectFromComposition; static HRESULT GetCandRectFromComposition(IMCLock& imc, LANGID langid, DWORD dwCharPos, RECT* out_rcArea) { HWND hDefImeWnd; if (IsWindow(hDefImeWnd=ImmGetDefaultIMEWnd(NULL))) { // // Internal notification to UI window // When receive this msg in UI wnd, then return candidate window rectangle // CandRectFromComposition lParam; lParam.langid = langid; lParam.dwCharPos = dwCharPos; lParam.out_rcArea = out_rcArea; SendMessage(hDefImeWnd, WM_IME_NOTIFY, IMN_PRIVATE_GETCANDRECTFROMCOMPOSITION, (LPARAM)&lParam); return S_OK; } return S_FALSE; } public: HRESULT GetSelection(IMCLock& imc, LONG *pacpSelStart, LONG *pcchSel); HRESULT OnPrivateGetCandRectFromComposition(IMCLock& imc, CandRectFromComposition* pv); HRESULT CreateDefFrameWnd(HWND hwndParent, HIMC hIMC); HRESULT CreateCompButtonWnd(HWND hwndParent, HIMC hIMC); HWND GetUIWnd() {return m_hUIWnd;} void OnSetCompositionTimerStatus(BOOL bSetTimer) {m_bTimerCOMPOSITION = bSetTimer;} private: LPWSTR GetCompStrBuffer(int nSize) { if (!m_lpszCompStr) { m_lpszCompStr = (LPWSTR)cicMemAllocClear((nSize + 1) * sizeof(WCHAR)); m_nCompStr = nSize; } if (m_nCompStr < nSize) { m_lpszCompStr = (LPWSTR)cicMemReAlloc(m_lpszCompStr, (nSize + 1) * sizeof(WCHAR)); m_nCompStr = nSize; } return m_lpszCompStr; } IME_UIWND_STATE GetLevelFromIMC(IMCLock& imc) { if (imc->cfCompForm.dwStyle == CFS_DEFAULT) return IME_UIWND_LEVEL1; if (imc->cfCompForm.dwStyle & (CFS_RECT | CFS_POINT | CFS_FORCE_POSITION)) { RECT rc; // // if there is no room to draw, try Level1. // GetClientRect(imc->hWnd, &rc); if (!PtInRect(&rc, imc->cfCompForm.ptCurrentPos)) return IME_UIWND_LEVEL1; // // if there is no room to draw, try Level1. // if (imc->cfCompForm.dwStyle & CFS_RECT) { if ((imc->cfCompForm.rcArea.top == imc->cfCompForm.rcArea.bottom) && (imc->cfCompForm.rcArea.left == imc->cfCompForm.rcArea.right)) return IME_UIWND_LEVEL1; } return IME_UIWND_LEVEL2; } return IME_UIWND_UNKNOWN; } private: HWND m_hUIWnd; static const LONG COMPUI_WINDOW_INDEX = 0; typedef enum tagCOMPWNDINDEX { FIRST_WINDOW, MIDDLE_WINDOW, LAST_WINDOW, END_OF_INDEX, // DEFAULT_WINDOW = -1 } COMPWNDINDEX; CBoolean m_fInitUIComp; COMPWND m_CompWnd[END_OF_INDEX]; COMPWND m_DefCompWnd; HFONT m_hFontLevel1; int m_tmFontHeightLevel1; HFONT m_hFontLevel2; int m_tmFontHeightLevel2; static const LONG CARET_WIDTH = 2; SIZE m_caret_size; static const LONG LINE_BOLD_WIDTH = 2; static const LONG LINE_SQUIGGLE_FREQUENCY = 4; static const LONG LINE_SQUIGGLE_AMPLITUDE = 2; DWORD m_isc; BOOL m_fActive; LPWSTR m_lpszCompStr; int m_nCompStr; BOOL m_bTimerCOMPOSITION; // when WM_IME_COMPOSITION is passed to the UI window, UIWnd procedure // start a timer for it. // this data member indicates if a timer is set and not handled (killed)yet. CBoolean m_fShowCompWnd; // When arrive WM_IME_COMPOSITION in UI window handler, UI Wnd might be Level 1 or Level 2 if // comp str is valid length and set ISC_SHOWUICOMPOSITIONWINDOW CDefCompFrameWindow *m_pDefCompFrameWnd; CCompButtonFrameWindow *m_pCompButtonFrameWnd; }; #endif // _UICOMP_H_