winamp/Src/Plugins/General/gen_ml/skinnededit.cpp
2024-09-24 14:54:57 +02:00

787 lines
20 KiB
C++

#include "./skinnededit.h"
#include "../winamp/wa_dlg.h"
#include "./skinning.h"
#include "./stockobjects.h"
#include "./skinnedmenu.h"
#include "../nu/trace.h"
#include <windowsx.h>
#include <strsafe.h>
#define EDIT_TEXT_MAX 65536
static WCHAR *pszTextGlobal = NULL;
static int caretPos = -1;
static BOOL updateCaret = FALSE;
#define GET_CHAR_X(__hwnd, __index) (GET_X_LPARAM(CallPrevWndProc(EM_POSFROMCHAR, (WPARAM)(__index), 0L)))
#define MLSEM_FIRST (WM_APP + 0x2FFE)
#define MLSEM_ENABLEREDRAW (MLSEM_FIRST - 0)
SkinnedEdit::SkinnedEdit(void) : SkinnedWnd(FALSE), firstVisible(0), lastVisible(0),
firstSelected(0), lastSelected(0), maxCharWidth(0),
mouseWParam(0), mouseLParam(0), cx(0), cy(0)
{
if (NULL == pszTextGlobal)
pszTextGlobal = (LPWSTR)calloc(EDIT_TEXT_MAX, sizeof(WCHAR));
}
SkinnedEdit::~SkinnedEdit(void)
{
}
BOOL SkinnedEdit::Attach(HWND hwndEdit)
{
if(!SkinnedWnd::Attach(hwndEdit)) return FALSE;
SetType(SKINNEDWND_TYPE_EDIT);
FontChanged();
SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
return TRUE;
}
void SkinnedEdit::EraseBckGnd(HDC hdc, RECT *prc, RECT *prcText, BOOL fEraseAll, HBRUSH hBrush)
{
HRGN rgn = CreateRectRgnIndirect(prc);
if (!IsRectEmpty(prcText))
{
HRGN rgn2 = CreateRectRgnIndirect(prcText);
if (NULL != rgn2)
{
CombineRgn(rgn, rgn, rgn2, RGN_DIFF);
/* if (FALSE != fEraseAll)
{
SetRectRgn(rgn2, prc->left, prc->top, prc->right, prcText->top);
CombineRgn(rgn, rgn, rgn2, RGN_DIFF);
SetRectRgn(rgn2, prc->left, prcText->bottom, prc->right, prc->bottom);
CombineRgn(rgn, rgn, rgn2, RGN_DIFF);
}*/
DeleteObject(rgn2);
}
}
FillRgn(hdc, rgn, hBrush);
DeleteObject(rgn);
}
void SkinnedEdit::DrawText(HDC hdc, RECT *prc, RECT *prcText, LPCWSTR pszText, INT cchText)
{
if ((lastSelected != firstSelected) &&
(lastSelected > firstVisible) &&
(firstSelected < lastVisible) &&
((hwnd == GetFocus()) || (ES_NOHIDESEL & GetWindowLongPtrW(hwnd, GWL_STYLE))))
{
RECT rt;
int lim, limSel;
LPCWSTR pszTextOut;
pszTextOut = pszText + firstVisible;
lim = firstSelected - firstVisible;
CopyRect(&rt, prcText);
if (lim > 0)
{
// DrawTextW(hdc, pszTextOut, lim, prcText,DT_TOP | DT_EDITCONTROL | DT_NOPREFIX | DT_NOCLIP);
ExtTextOutW(hdc, rt.left, rt.top, 0, &rt, pszTextOut, lim, NULL);
pszTextOut += lim;
}
limSel = min(lastSelected, lastVisible) - (int)(pszTextOut - pszText);
lim = lastVisible - lastSelected;
if(lim > 0)
{
rt.left = GET_CHAR_X(hwnd, lastSelected);
// DrawTextW(hdc, pszTextOut + limSel, lim, &rt, DT_TOP | DT_EDITCONTROL | DT_NOPREFIX | DT_NOCLIP);
ExtTextOutW(hdc, rt.left, rt.top, 0, &rt, pszTextOut + limSel, lim, NULL);
}
SetTextColor(hdc, WADlg_getColor(WADLG_SELBAR_FGCOLOR));
SetBkColor(hdc, WADlg_getColor(WADLG_SELBAR_BGCOLOR));
if (lim > 0) rt.right = rt.left - 1;
rt.left = GET_CHAR_X(hwnd, max(firstSelected, firstVisible));
// DrawTextW(hdc, pszTextOut, limSel, &rt, DT_TOP | DT_EDITCONTROL | DT_NOPREFIX | DT_NOCLIP );
if (rt.right > rt.left) ExtTextOutW(hdc, rt.left, rt.top, ETO_CLIPPED, &rt, pszTextOut, limSel, NULL);
}
else
{
// DrawTextW(hdc, pszText + firstVisible, cchText - firstVisible - (cchText - lastVisible), prcText, DT_TOP | DT_NOPREFIX | DT_NOCLIP);
ExtTextOutW(hdc, prcText->left, prcText->top, 0, prcText,
pszText+ firstVisible, cchText - firstVisible - (cchText - lastVisible), NULL);
}
}
static void GetEditColors(DWORD windowStyle, BOOL bEnabled, COLORREF *prgbText, COLORREF *prgbTextBk)
{
COLORREF fg, bg;
bg = WADlg_getColor((ES_READONLY & windowStyle) ? WADLG_WNDBG : WADLG_ITEMBG);
fg = WADlg_getColor((ES_READONLY & windowStyle) ? WADLG_WNDFG : WADLG_ITEMFG);
if(!bEnabled)
{
fg = RGB((GetRValue(fg)+GetRValue(bg))/2,
(GetGValue(fg)+GetGValue(bg))/2,
(GetBValue(fg)+GetBValue(bg))/2);
}
if (prgbText) *prgbText = fg;
if (prgbTextBk) *prgbTextBk = bg;
}
void SkinnedEdit::OnPaint()
{
HDC hdc;
int cchText;
PAINTSTRUCT ps;
RECT rc, rt;
HFONT hFont, hFontOld;
DWORD margins, ws;
TEXTMETRICW tm;
cchText = (INT)CallPrevWndProc(WM_GETTEXTLENGTH, 0, 0);
if (cchText) CallPrevWndProc(WM_GETTEXT, (WPARAM)EDIT_TEXT_MAX, (LPARAM)pszTextGlobal);
hFont = (HFONT)CallPrevWndProc(WM_GETFONT, 0, 0L);
if (!hFont) hFont = (HFONT)MlStockObjects_Get(DEFAULT_FONT);
hdc = GetDCEx(hwnd, NULL, DCX_PARENTCLIP | DCX_CACHE | DCX_CLIPSIBLINGS |
DCX_INTERSECTUPDATE | DCX_VALIDATE);
if (NULL == hdc) return;
hFontOld = (hFont) ? (HFONT)SelectObject(hdc, hFont) : NULL;
GetTextMetricsW(hdc, &tm);
GetClientRect(hwnd, &rc);
CopyRect(&rt, &rc);
if (SWES_BOTTOM & style)
{
if ((rt.bottom - tm.tmHeight) > rt.top) rt.top = rt.bottom - tm.tmHeight;
}
else if (SWES_VCENTER & style)
{
INT t = rc.top + ((rc.bottom - rc.top) - tm.tmHeight)/2;
if (t > rc.top) rt.top = t;
}
ws = GetWindowLongPtrW(hwnd, GWL_STYLE);
margins = (DWORD)CallPrevWndProc(EM_GETMARGINS, 0, 0L);
if (cchText)
{
int x;
CallPrevWndProc(EM_GETSEL, (WPARAM)&firstSelected, (LPARAM)&lastSelected);
lastVisible = (int)(INT_PTR)CallPrevWndProc(EM_CHARFROMPOS, 0, MAKELPARAM(rc.right - (GET_Y_LPARAM(margins)), 0));
if ( -1 == lastVisible) lastVisible = cchText;
firstVisible =(INT)(INT_PTR)CallPrevWndProc(EM_CHARFROMPOS, 0, MAKELPARAM(rc.left + GET_X_LPARAM(margins), 0));
if (cchText == firstVisible) firstVisible = 0;
else if (firstVisible > 0) firstVisible++;
while (12000 < (x = GET_CHAR_X(hwnd, firstVisible))) firstVisible++;
rt.left = x;
if (firstVisible > 0 && rt.left > rc.left + GET_X_LPARAM(margins) + 1)
{ // we can try to display one more
int t = GET_CHAR_X(hwnd, firstVisible -1);
if (t != -1 && t < rc.right) { rt.left = t; firstVisible--; }
}
if (lastVisible)
{
if (lastVisible < cchText -1)
{
rt.right = GET_CHAR_X(hwnd, lastVisible);
}
else
{
INT i = lastVisible - ((cchText == lastVisible && cchText) ? 1 : 0);
ABC abc;
if (GetCharABCWidthsW(hdc, pszTextGlobal[i], pszTextGlobal[i], &abc))
rt.right = abc.abcA + abc.abcB + abc.abcC;
else
GetCharWidth32W(hdc, pszTextGlobal[i], pszTextGlobal[i], (INT*)&rt.right);
rt.right += GET_CHAR_X(hwnd, i);
}
}
else rt.right = rt.left;
if (rt.top + tm.tmHeight < rt.bottom) rt.bottom = rt.top + tm.tmHeight;
if (rt.right > rc.right - GET_Y_LPARAM(margins)) rt.right = rc.right - GET_Y_LPARAM(margins);
}
else
{
firstVisible = 0;
lastVisible = 0;
rt.left += GET_X_LPARAM(margins);
rt.right -= GET_Y_LPARAM(margins);
if (ES_CENTER & ws)
{
rt.left += (rt.right - rt.left)/2;
rt.right = rt.left;
}
else if (ES_RIGHT & ws) rt.left = rt.right;
else rt.right = rt.left;
}
if (FALSE != updateCaret)
{
updateCaret = FALSE;
// ShowCaret(hwnd);
if (hwnd == GetFocus())
{
INT x;
if (caretPos >= lastVisible) x = rt.right;
else if (caretPos <= firstVisible) x = rt.left;
else x = GET_CHAR_X(hwnd, caretPos);
if (x < rc.left)
x = rc.left;
else
{
INT caretWidth = GetSystemMetrics(SM_CXBORDER);
if (x + caretWidth > rc.right)
x = rc.right - caretWidth;
}
SetCaretPos(x, rt.top);
}
}
if (hFontOld) SelectObject(hdc, hFontOld);
ReleaseDC(hwnd, hdc);
hdc = BeginPaint(hwnd, &ps);
if (NULL == hdc) return;
hFontOld = (hFont) ? (HFONT)SelectObject(hdc, hFont) : NULL;
HBRUSH brushBk = NULL;
BOOL overrideColors = FALSE;
HWND hParent = GetParent(hwnd);
if (NULL != hParent)
{
UINT uMsg = (0 == ((ES_READONLY | WS_DISABLED) & ws)) ? WM_CTLCOLOREDIT : WM_CTLCOLORSTATIC;
brushBk = (HBRUSH)SendMessage(hParent, uMsg, (WPARAM)hdc, (LPARAM)hwnd);
HBRUSH stockBursh = GetSysColorBrush( (0 == ((ES_READONLY | WS_DISABLED) & ws)) ? COLOR_WINDOW : COLOR_3DFACE);
if (NULL == brushBk || stockBursh == brushBk)
overrideColors = TRUE;
}
if (FALSE != overrideColors)
{
COLORREF rgbText, rgbTextBk;
GetEditColors(ws, IsWindowEnabled(hwnd), &rgbText, &rgbTextBk);
SetBkColor(hdc, rgbTextBk);
SetTextColor(hdc, rgbText);
brushBk = (HBRUSH)MlStockObjects_Get((ES_READONLY & ws) ? WNDBCK_BRUSH : ITEMBCK_BRUSH);
}
IntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom);
EraseBckGnd(hdc, &rc, NULL, ps.fErase, brushBk);
if (cchText)
{
IntersectClipRect(hdc, rc.left + GET_X_LPARAM(margins), rt.top, rc.right - GET_Y_LPARAM(margins), rt.bottom);
DrawText(hdc, &rc, &rt, pszTextGlobal, cchText);
}
if (hFontOld) SelectObject(hdc, hFontOld);
EndPaint(hwnd, &ps);
}
void SkinnedEdit::OnSkinUpdated(BOOL bNotifyChildren, BOOL bRedraw)
{
__super::OnSkinUpdated(bNotifyChildren, bRedraw);
if (SWS_USESKINFONT & style)
{
CallPrevWndProc(EM_SETMARGINS, (WPARAM)(EC_LEFTMARGIN | EC_RIGHTMARGIN), MAKELPARAM(EC_USEFONTINFO, EC_USEFONTINFO));
}
}
BOOL SkinnedEdit::GetSelection(SELECTION *selection, INT cchText, const RECT *clientRect)
{
if (NULL == selection) return FALSE;
if (0 == cchText)
{
selection->first = 0;
selection->last = 0;
selection->leftX = clientRect->left;
selection->rightX = clientRect->left;
return TRUE;
}
CallPrevWndProc(EM_GETSEL, (WPARAM)&selection->first, (LPARAM)&selection->last);
selection->leftX = GET_CHAR_X(hwnd, selection->first);
if (-1 == selection->last || cchText == selection->last)
{
selection->last = cchText;
selection->rightX = GET_CHAR_X(hwnd, cchText - 1) + maxCharWidth;
}
else
{
selection->rightX = GET_CHAR_X(hwnd, selection->last);
}
return TRUE;
}
LRESULT SkinnedEdit::OverrideDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LRESULT result;
UINT windowStyle = GetWindowStyle(hwnd);
if (0 == (WS_VISIBLE & windowStyle))
{
result = __super::WindowProc(uMsg, wParam, lParam);
return result;
}
SELECTION selectionOrig;
RECT ri;
GetClientRect(hwnd, &ri);
INT lengthOrig = (INT)CallPrevWndProc(WM_GETTEXTLENGTH, 0, 0L);
INT startXOrig = (lengthOrig > 0) ? GET_CHAR_X(hwnd, 0) : 0;
GetSelection(&selectionOrig, lengthOrig, &ri);
SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle & ~ WS_VISIBLE);
result = __super::WindowProc(uMsg, wParam, lParam);
windowStyle = GetWindowStyle(hwnd);
if (0 == (WS_VISIBLE & windowStyle))
{
windowStyle |= WS_VISIBLE;
SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle);
}
if (hwnd == GetFocus())
{
INT length = (INT)CallPrevWndProc(WM_GETTEXTLENGTH, 0, 0L);
SELECTION selection;
GetSelection(&selection, length, &ri);
if (selectionOrig.first != selection.first || selectionOrig.last != selection.last || lengthOrig != length )
{
caretPos = (selectionOrig.last != selection.last) ? selection.last : selection.first;
if( FALSE == updateCaret)
updateCaret = TRUE;
if (0 != (WS_VISIBLE & windowStyle))
{
INT startX = (lengthOrig > 0) ? GET_CHAR_X(hwnd, 0) : 0;
if (lengthOrig != length || startXOrig != startX)
{
RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_VALIDATE | RDW_INTERNALPAINT | RDW_NOERASE | RDW_ERASENOW | RDW_UPDATENOW | RDW_NOCHILDREN);
}
else
{
//RECT ri;
GetClientRect(hwnd, &ri);
if (selectionOrig.first != selectionOrig.last)
{
if (selectionOrig.rightX > selection.leftX && selectionOrig.rightX < selection.rightX)
selectionOrig.rightX--;
if (selectionOrig.leftX > selection.leftX && selectionOrig.leftX < selection.rightX)
selectionOrig.leftX++;
}
// aTRACE_FMT("redraw: (%d, %d) - (%d, %d)\r\n",selectionOrig.leftX, selectionOrig.rightX, selection.leftX, selection.rightX);
HRGN rgn1 = CreateRectRgn(selectionOrig.leftX, ri.top, selectionOrig.rightX, ri.bottom);
HRGN rgn2 = CreateRectRgn(selection.leftX, ri.top, selection.rightX, ri.bottom);
CombineRgn(rgn1, rgn1, rgn2, (selectionOrig.first != selectionOrig.last) ? RGN_XOR : RGN_OR);
POINT caretPt;
if (FALSE != GetCaretPos(&caretPt))
{
INT caretWidth = GetSystemMetrics(SM_CXBORDER);
if (0 == caretWidth) caretWidth = 1;
SetRectRgn(rgn2, caretPt.x, ri.top, caretPt.x + caretWidth, ri.bottom);
CombineRgn(rgn1, rgn1, rgn2, RGN_OR);
}
RedrawWindow(hwnd, NULL, rgn1, RDW_INVALIDATE | RDW_NOERASE | RDW_ERASENOW | RDW_UPDATENOW);
INT scrollCX = 0;
if (selectionOrig.first == selection.first && selectionOrig.leftX != selection.leftX)
{
scrollCX = selectionOrig.leftX - selection.leftX;
}
if (selectionOrig.last == selection.last && selectionOrig.rightX != selection.rightX)
{
scrollCX = selectionOrig.rightX - selection.rightX;
}
if (0 != scrollCX)
{
if (scrollCX > 0)
aTRACE_LINE("move on left side");
else
aTRACE_LINE("move on right side");
}
DeleteObject(rgn1);
DeleteObject(rgn2);
}
}
}
}
return result;
}
void SkinnedEdit::OnWindowPosChanged(WINDOWPOS *pwp)
{
HRGN updateRgn = CreateRectRgn(0, 0, 0, 0);
UINT windowStyle = GetWindowStyle(hwnd);
if (0 != (WS_VISIBLE & windowStyle))
{
if (NULL != updateRgn)
{
GetUpdateRgn(hwnd, updateRgn, FALSE);
}
SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle & ~ WS_VISIBLE);
}
__super::WindowProc(WM_WINDOWPOSCHANGED, 0, (LPARAM)pwp);
if (0 != (WS_VISIBLE & windowStyle))
{
windowStyle = GetWindowStyle(hwnd);
if (0 == (WS_VISIBLE & windowStyle))
SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle | WS_VISIBLE);
}
RECT rc;
GetClientRect(hwnd, &rc);
if( FALSE == updateCaret)
{
updateCaret = TRUE;
// HideCaret(hwnd);
}
if (0 == ((SWP_NOSIZE | SWP_NOREDRAW) & pwp->flags))
{
HRGN rgn = NULL;
if (rc.right - rc.left != cx)
{
cx -= GET_Y_LPARAM((DWORD)CallPrevWndProc(EM_GETMARGINS, 0, 0L));
cx -= maxCharWidth;
LONG l = rc.left;
rc.left = cx;
if (NULL != rgn) SetRectRgn(rgn, rc.left, rc.top, rc.right, rc.bottom);
else rgn = CreateRectRgnIndirect(&rc);
rc.left = l;
}
if (rc.bottom - rc.top != cy)
{
LONG t = rc.top;
rc.top = cy;
if (NULL != rgn) SetRectRgn(rgn, rc.left, rc.top, rc.right, rc.bottom);
else rgn = CreateRectRgnIndirect(&rc);
CombineRgn(updateRgn, updateRgn, rgn, RGN_OR);
rc.top = t;
}
if (0 == (SWP_NOREDRAW & pwp->flags))
{
if (NULL != updateRgn)
InvalidateRgn(hwnd, updateRgn, FALSE);
}
if (NULL != rgn)
DeleteObject(rgn);
}
cx = rc.right - rc.left;
cy = rc.bottom - rc.top;
if (NULL != updateRgn)
DeleteObject(updateRgn);
}
void SkinnedEdit::FontChanged()
{
HDC hdc = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS);
if (NULL != hdc)
{
HFONT font, fontOrig;
font = (HFONT)CallPrevWndProc(WM_GETFONT, 0, 0L);
if (NULL != font)
fontOrig = (HFONT)SelectObject(hdc, font);
TEXTMETRICW tm;
maxCharWidth = (FALSE != GetTextMetricsW(hdc, &tm)) ? tm.tmMaxCharWidth : 0;
if (NULL != font)
SelectObject(hdc, fontOrig);
ReleaseDC(hwnd, hdc);
}
}
void SkinnedEdit::OnSetFont(HFONT hFont, BOOL fRedraw)
{
__super::WindowProc(WM_SETFONT, (WPARAM)hFont, (LPARAM)fRedraw);
FontChanged();
}
LRESULT SkinnedEdit::WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if ( 0 != (SWES_SELECTONCLICK & style))
{
switch(uMsg)
{
case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
if (hwnd != GetFocus())
{
CallPrevWndProc(EM_SETSEL, 0, -1);
SetFocus(hwnd);
if (WM_LBUTTONDOWN == uMsg) return 0;
}
break;
}
}
if (SWS_USESKINCOLORS & style)
{
UINT windowStyle = GetWindowStyle(hwnd);
switch(uMsg)
{
case WM_CONTEXTMENU:
if (IsSkinnedPopupEnabled(FALSE))
{
SkinnedMenu sm;
if (sm.InitializeHook(hwnd, SMS_USESKINFONT, NULL, 0, NULL, 0L))
{
__super::WindowProc(uMsg, wParam, lParam);
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
return 0;
}
}
break;
case MLSEM_ENABLEREDRAW:
windowStyle = GetWindowStyle(hwnd);
if (0 == (WS_VISIBLE & windowStyle))
{
SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle | WS_VISIBLE);
}
return 0;
}
if (0 == (ES_MULTILINE & windowStyle))
{
switch(uMsg)
{
case WM_PAINT: OnPaint(); return 0;
case WM_ERASEBKGND: return 0;
case WM_SETFONT: OnSetFont((HFONT)wParam, (BOOL)lParam); return 0;
case WM_MOUSEMOVE:
if (wParam == mouseWParam && lParam == mouseLParam) return 0;
mouseWParam = wParam;
mouseLParam = lParam;
return (MK_LBUTTON & mouseWParam) ? OverrideDefault(uMsg, wParam, lParam) : 0;
case WM_SETFOCUS:
caretPos = -1;
case WM_CAPTURECHANGED:
if (0 != (WS_VISIBLE & windowStyle))
SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle & ~WS_VISIBLE);
__super::WindowProc(uMsg, wParam, lParam);
if (0 != (WS_VISIBLE & windowStyle))
{
windowStyle = GetWindowStyle(hwnd);
if (0 == (WS_VISIBLE & windowStyle))
{
SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle | WS_VISIBLE);
InvalidateRect(hwnd, NULL, FALSE);
}
}
if (FALSE == updateCaret)
{
// HideCaret(hwnd);
updateCaret = TRUE;
}
return 0;
case WM_UPDATEUISTATE:
case WM_KILLFOCUS:
if (0 != (WS_VISIBLE & windowStyle))
SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle & ~WS_VISIBLE);
__super::WindowProc(uMsg, wParam, lParam);
if (0 != (WS_VISIBLE & windowStyle))
{
windowStyle = GetWindowStyle(hwnd);
if (0 == (WS_VISIBLE & windowStyle))
{
SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle | WS_VISIBLE);
RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE);
}
}
return 0;
case WM_WINDOWPOSCHANGED:
OnWindowPosChanged((WINDOWPOS*)lParam);
return 0;
case WM_SETTEXT:
if (OverrideDefault(uMsg, wParam, lParam))
{
InvalidateRect(hwnd, NULL, TRUE);
return TRUE;
}
return FALSE;
case EM_SETSEL:
{
BOOL recoverRegion = FALSE;
HRGN windowRegion = CreateRectRgn(0, 0, 0, 0);
INT result = GetWindowRgn(hwnd, windowRegion);
if (SIMPLEREGION != result && COMPLEXREGION != result)
{
DeleteObject(windowRegion);
windowRegion = NULL;
}
if (0 != (WS_VISIBLE & windowStyle))
SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle & ~WS_VISIBLE);
HRGN fakeRegion = CreateRectRgn(0, 0, 0, 0);
if (0 != SetWindowRgn(hwnd, fakeRegion, FALSE))
recoverRegion = TRUE;
INT prevFirst, prevLast, currFirst, currLast;
CallPrevWndProc(EM_GETSEL, (WPARAM)&prevFirst, (LPARAM)&prevLast);
__super::WindowProc(uMsg, wParam, lParam);
CallPrevWndProc(EM_GETSEL, (WPARAM)&currFirst, (LPARAM)&currLast);
if (currFirst != prevFirst || currLast != prevLast)
{
if (currLast != prevLast) caretPos = currLast;
else caretPos = currFirst;
if (FALSE == updateCaret)
{
// HideCaret(hwnd);
updateCaret = TRUE;
}
}
if (FALSE != recoverRegion)
SetWindowRgn(hwnd, windowRegion, FALSE);
if (NULL != windowRegion)
{
DeleteObject(windowRegion);
windowRegion = NULL;
}
if (0 != (WS_VISIBLE & windowStyle))
{
windowStyle = GetWindowStyle(hwnd);
if (0 == (WS_VISIBLE & windowStyle))
{
SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle | WS_VISIBLE);
InvalidateRect(hwnd, NULL, FALSE);
}
}
}
return 0;
case WM_LBUTTONUP:
{
if (0 != (WS_VISIBLE & windowStyle))
SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle & ~WS_VISIBLE);
__super::WindowProc(uMsg, wParam, lParam);
if (0 != (WS_VISIBLE & windowStyle))
{
windowStyle = GetWindowStyle(hwnd);
if (0 == (WS_VISIBLE & windowStyle))
SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle | WS_VISIBLE);
}
}
return 0;
case WM_CHAR:
case WM_KEYDOWN:
case WM_CUT:
//case WM_PASTE:
case WM_CLEAR:
case WM_UNDO:
case EM_UNDO:
case WM_LBUTTONDBLCLK:
case WM_LBUTTONDOWN:
return OverrideDefault(uMsg, wParam, lParam);
}
}
}
switch(uMsg)
{
case WM_SETCURSOR:
if ((HWND)wParam == hwnd && HTCLIENT == LOWORD(lParam))
{
HCURSOR cursor;
cursor = LoadCursor(NULL, IDC_IBEAM);
if (NULL != cursor)
{
SetCursor(cursor);
return TRUE;
}
}
break;
}
return __super::WindowProc(uMsg, wParam, lParam);
}