mirror of
https://github.com/WinampDesktop/winamp.git
synced 2024-09-24 15:54:12 +00:00
787 lines
20 KiB
C++
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);
|
|
}
|
|
|