1241 lines
32 KiB
C++
1241 lines
32 KiB
C++
|
#include "main.h"
|
||
|
#include "./embeddedEditor.h"
|
||
|
#include <vector>
|
||
|
|
||
|
#define EMBEDDEDEDITOR_FRAME_LEFT 1
|
||
|
#define EMBEDDEDEDITOR_FRAME_TOP 1
|
||
|
#define EMBEDDEDEDITOR_FRAME_RIGHT 1
|
||
|
#define EMBEDDEDEDITOR_FRAME_BOTTOM 1
|
||
|
|
||
|
#define EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_LEFT 1
|
||
|
#define EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_TOP 1
|
||
|
#define EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_RIGHT 1
|
||
|
#define EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_BOTTOM 1
|
||
|
|
||
|
#define EMBEDDEDEDITOR_FRAME_INNER_SPACE_LEFT 0
|
||
|
#define EMBEDDEDEDITOR_FRAME_INNER_SPACE_TOP 0
|
||
|
#define EMBEDDEDEDITOR_FRAME_INNER_SPACE_RIGHT 0
|
||
|
#define EMBEDDEDEDITOR_FRAME_INNER_SPACE_BOTTOM 0
|
||
|
|
||
|
#define EMBEDDEDEDITOR_MARGIN_LEFT 4
|
||
|
#define EMBEDDEDEDITOR_MARGIN_TOP 1
|
||
|
#define EMBEDDEDEDITOR_MARGIN_RIGHT 4
|
||
|
#define EMBEDDEDEDITOR_MARGIN_BOTTOM 1
|
||
|
|
||
|
|
||
|
#define EMBEDDEDEDITOR_BORDER_LEFT (EMBEDDEDEDITOR_FRAME_LEFT + \
|
||
|
EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_LEFT + \
|
||
|
EMBEDDEDEDITOR_FRAME_INNER_SPACE_LEFT)
|
||
|
|
||
|
#define EMBEDDEDEDITOR_BORDER_TOP (EMBEDDEDEDITOR_FRAME_TOP + \
|
||
|
EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_TOP + \
|
||
|
EMBEDDEDEDITOR_FRAME_INNER_SPACE_TOP)
|
||
|
|
||
|
#define EMBEDDEDEDITOR_BORDER_RIGHT (EMBEDDEDEDITOR_FRAME_RIGHT + \
|
||
|
EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_RIGHT + \
|
||
|
EMBEDDEDEDITOR_FRAME_INNER_SPACE_RIGHT)
|
||
|
|
||
|
#define EMBEDDEDEDITOR_BORDER_BOTTOM (EMBEDDEDEDITOR_FRAME_BOTTOM + \
|
||
|
EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_BOTTOM + \
|
||
|
EMBEDDEDEDITOR_FRAME_INNER_SPACE_BOTTOM)
|
||
|
|
||
|
|
||
|
typedef struct EmbeddedEditor
|
||
|
{
|
||
|
WNDPROC originalProc;
|
||
|
COLORREF textColor;
|
||
|
COLORREF backColor;
|
||
|
COLORREF borderColor;
|
||
|
HBRUSH backBrush;
|
||
|
HBRUSH borderBrush;
|
||
|
EmbeddedEditorFinishCb callback;
|
||
|
void *user;
|
||
|
POINT anchorPoint;
|
||
|
SIZE maximumSize;
|
||
|
wchar_t *buffer;
|
||
|
size_t bufferSize;
|
||
|
long spacing;
|
||
|
long lineHeight;
|
||
|
} EmbeddedEditor;
|
||
|
|
||
|
typedef std::vector<HWND> WindowList;
|
||
|
|
||
|
typedef struct EmbeddedEditorParent
|
||
|
{
|
||
|
WNDPROC originalProc;
|
||
|
WindowList editorList;
|
||
|
} EmbeddedEditorParent;
|
||
|
|
||
|
|
||
|
typedef struct EmbeddedEditorThread
|
||
|
{
|
||
|
HHOOK hook;
|
||
|
HWND window;
|
||
|
} EmbeddedEditorThread;
|
||
|
|
||
|
static size_t editorTls = ((size_t)-1);
|
||
|
|
||
|
static ATOM EMBEDDEDEDITOR_PROP = 0;
|
||
|
|
||
|
#define EMBEDDEDEDITOR(_hwnd) ((EmbeddedEditor*)GetPropW((_hwnd), MAKEINTATOM(EMBEDDEDEDITOR_PROP)))
|
||
|
#define EMBEDDEDEDITOR_RET_VOID(_self, _hwnd) { (_self) = EMBEDDEDEDITOR((_hwnd)); if (NULL == (_self)) return; }
|
||
|
#define EMBEDDEDEDITOR_RET_VAL(_self, _hwnd, _error) { (_self) = EMBEDDEDEDITOR((_hwnd)); if (NULL == (_self)) return (_error); }
|
||
|
|
||
|
#define EMBEDDEDEDITOR_PARENT(_hwnd) ((EmbeddedEditorParent*)GetPropW((_hwnd), MAKEINTATOM(EMBEDDEDEDITOR_PROP)))
|
||
|
|
||
|
static LRESULT WINAPI
|
||
|
EmbeddedEditor_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||
|
|
||
|
static LRESULT WINAPI
|
||
|
EmbeddedEditorParent_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||
|
|
||
|
static LRESULT CALLBACK
|
||
|
EmbeddidEditorThread_MouseProc(int code, unsigned int messageId, MOUSEHOOKSTRUCT *mouse);
|
||
|
|
||
|
static BOOL
|
||
|
EmbeddidEditorThread_BeginMouseMonitor(HWND editorWindow)
|
||
|
{
|
||
|
EmbeddedEditorThread *threadData;
|
||
|
|
||
|
if (NULL == WASABI_API_APP ||
|
||
|
NULL == editorWindow)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if ((size_t)-1 == editorTls)
|
||
|
{
|
||
|
editorTls = WASABI_API_APP->AllocateThreadStorage();
|
||
|
if ((size_t)-1 == editorTls)
|
||
|
return FALSE;
|
||
|
|
||
|
threadData = NULL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
threadData = (EmbeddedEditorThread*)WASABI_API_APP->GetThreadStorage(editorTls);
|
||
|
WASABI_API_APP->SetThreadStorage(editorTls, NULL);
|
||
|
}
|
||
|
|
||
|
if (NULL != threadData)
|
||
|
{
|
||
|
if (NULL != threadData->window)
|
||
|
DestroyWindow(threadData->window);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
threadData = (EmbeddedEditorThread*)malloc(sizeof(EmbeddedEditorThread));
|
||
|
if (NULL == threadData)
|
||
|
return FALSE;
|
||
|
|
||
|
threadData->hook = SetWindowsHookEx(WH_MOUSE, (HOOKPROC)EmbeddidEditorThread_MouseProc, NULL, GetCurrentThreadId());
|
||
|
if (NULL == threadData->hook)
|
||
|
{
|
||
|
free(threadData);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
threadData->window = editorWindow;
|
||
|
WASABI_API_APP->SetThreadStorage(editorTls, threadData);
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
EmbeddidEditorThread_EndMouseMonitor(HWND editorWindow)
|
||
|
{
|
||
|
EmbeddedEditorThread *threadData;
|
||
|
|
||
|
if (NULL == WASABI_API_APP ||
|
||
|
(size_t)-1 == editorTls ||
|
||
|
NULL == editorWindow)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
threadData = (EmbeddedEditorThread*)WASABI_API_APP->GetThreadStorage(editorTls);
|
||
|
WASABI_API_APP->SetThreadStorage(editorTls, NULL);
|
||
|
|
||
|
if (NULL != threadData)
|
||
|
{
|
||
|
if (NULL != threadData->hook)
|
||
|
UnhookWindowsHookEx(threadData->hook);
|
||
|
|
||
|
free(threadData);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static BOOL
|
||
|
EmbeddedEditorParent_AddChild(HWND hwnd, HWND child)
|
||
|
{
|
||
|
EmbeddedEditorParent *self;
|
||
|
|
||
|
if (NULL == hwnd || NULL == child)
|
||
|
return FALSE;
|
||
|
|
||
|
self = EMBEDDEDEDITOR_PARENT(hwnd);
|
||
|
|
||
|
if (NULL == self)
|
||
|
{
|
||
|
self = new EmbeddedEditorParent();
|
||
|
if (NULL == self)
|
||
|
return FALSE;
|
||
|
|
||
|
self->originalProc = (WNDPROC)(LONG_PTR)SetWindowLongPtr(hwnd, GWLP_WNDPROC,
|
||
|
(LONGX86)(LONG_PTR)EmbeddedEditorParent_WindowProc);
|
||
|
|
||
|
if (NULL != self->originalProc &&
|
||
|
FALSE == SetProp(hwnd, MAKEINTATOM(EMBEDDEDEDITOR_PROP), self))
|
||
|
{
|
||
|
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)self->originalProc);
|
||
|
delete self;
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
size_t index;
|
||
|
index = self->editorList.size();
|
||
|
while(index--)
|
||
|
{
|
||
|
if (self->editorList[index] == child)
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
self->editorList.push_back(child);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
static BOOL
|
||
|
EmbeddedEditorParent_RemoveChild(HWND hwnd, HWND child)
|
||
|
{
|
||
|
size_t index;
|
||
|
EmbeddedEditorParent *self;
|
||
|
|
||
|
if (NULL == hwnd || NULL == child)
|
||
|
return FALSE;
|
||
|
|
||
|
self = EMBEDDEDEDITOR_PARENT(hwnd);
|
||
|
if (NULL == self)
|
||
|
return FALSE;
|
||
|
|
||
|
index = self->editorList.size();
|
||
|
while(index--)
|
||
|
{
|
||
|
if (self->editorList[index] == child)
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (((size_t)-1) == index)
|
||
|
return FALSE;
|
||
|
|
||
|
self->editorList.erase(self->editorList.begin() + index);
|
||
|
if (0 == self->editorList.size())
|
||
|
{
|
||
|
RemoveProp(hwnd, MAKEINTATOM(EMBEDDEDEDITOR_PROP));
|
||
|
|
||
|
if (NULL != self->originalProc)
|
||
|
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)self->originalProc);
|
||
|
|
||
|
delete self;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
EmbeddedEditor_Attach(HWND hwnd, EmbeddedEditorFinishCb callback, void *user)
|
||
|
{
|
||
|
HWND parent;
|
||
|
EmbeddedEditor *self;
|
||
|
|
||
|
if (NULL == hwnd)
|
||
|
return FALSE;
|
||
|
|
||
|
if (0 == EMBEDDEDEDITOR_PROP)
|
||
|
{
|
||
|
EMBEDDEDEDITOR_PROP = GlobalAddAtom(TEXT("EmdeddedEditorProp"));
|
||
|
if (0 == EMBEDDEDEDITOR_PROP)
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
self = (EmbeddedEditor*)malloc(sizeof(EmbeddedEditor));
|
||
|
if (NULL == self)
|
||
|
return FALSE;
|
||
|
|
||
|
memset(self, 0, sizeof(EmbeddedEditor));
|
||
|
|
||
|
self->originalProc = (WNDPROC)(LONG_PTR)SetWindowLongPtr(hwnd, GWLP_WNDPROC,
|
||
|
(LONGX86)(LONG_PTR)EmbeddedEditor_WindowProc);
|
||
|
|
||
|
if (NULL != self->originalProc &&
|
||
|
FALSE == SetProp(hwnd, MAKEINTATOM(EMBEDDEDEDITOR_PROP), self))
|
||
|
{
|
||
|
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)self->originalProc);
|
||
|
free(self);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
self->callback = callback;
|
||
|
self->user = user;
|
||
|
|
||
|
self->backColor = RGB(0, 0, 255); //GetSysColor(COLOR_WINDOW);
|
||
|
self->backBrush = NULL;
|
||
|
self->textColor = RGB(255, 255, 0); //GetSysColor(COLOR_WINDOWTEXT);
|
||
|
self->borderColor = RGB(255, 0, 0); //GetSysColor(COLOR_WINDOWFRAME);
|
||
|
self->borderBrush = NULL;
|
||
|
self->spacing = -1;
|
||
|
self->lineHeight = -1;
|
||
|
|
||
|
parent = GetAncestor(hwnd, GA_PARENT);
|
||
|
if(NULL != parent)
|
||
|
EmbeddedEditorParent_AddChild(parent, hwnd);
|
||
|
|
||
|
EmbeddidEditorThread_BeginMouseMonitor(hwnd);
|
||
|
|
||
|
RECT rect, formatRect;
|
||
|
GetWindowRect(hwnd, &rect);
|
||
|
SetRect(&formatRect, 0, 0, RECTWIDTH(rect) - 6, RECTHEIGHT(rect) - 6);
|
||
|
SendMessage(hwnd, EM_SETRECTNP, 0, (LPARAM)&formatRect);
|
||
|
|
||
|
SetWindowPos(hwnd, NULL, 0, 0, 0, 0,
|
||
|
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE | SWP_FRAMECHANGED);
|
||
|
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
EmbeddedEditor_AdjustWindowRectEx(RECT *rect, unsigned long styleEx, unsigned long style)
|
||
|
{
|
||
|
if (NULL == rect)
|
||
|
return FALSE;
|
||
|
|
||
|
if (0 != ((WS_EX_STATICEDGE | WS_EX_CLIENTEDGE) & styleEx) ||
|
||
|
0 != (WS_BORDER & style))
|
||
|
{
|
||
|
rect->left -= (EMBEDDEDEDITOR_BORDER_LEFT + EMBEDDEDEDITOR_MARGIN_LEFT);
|
||
|
rect->top -= (EMBEDDEDEDITOR_BORDER_TOP + EMBEDDEDEDITOR_MARGIN_TOP);
|
||
|
rect->right += (EMBEDDEDEDITOR_BORDER_RIGHT + EMBEDDEDEDITOR_MARGIN_RIGHT);
|
||
|
rect->bottom += (EMBEDDEDEDITOR_BORDER_BOTTOM + EMBEDDEDEDITOR_MARGIN_BOTTOM);
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
static HBRUSH
|
||
|
EmbeddedEditor_GetBackBrush(EmbeddedEditor *self)
|
||
|
{
|
||
|
if (NULL == self->backBrush)
|
||
|
self->backBrush = CreateSolidBrush(self->backColor);
|
||
|
|
||
|
return self->backBrush;
|
||
|
}
|
||
|
|
||
|
static HBRUSH
|
||
|
EmbeddedEditor_GetBorderBrush(EmbeddedEditor *self)
|
||
|
{
|
||
|
if (NULL == self->borderBrush)
|
||
|
self->borderBrush = CreateSolidBrush(self->borderColor);
|
||
|
|
||
|
return self->borderBrush;
|
||
|
}
|
||
|
|
||
|
static BOOL
|
||
|
EmbdeddedEditor_GetBorderEnabled(HWND hwnd)
|
||
|
{
|
||
|
unsigned long style;
|
||
|
|
||
|
style = GetWindowStyleEx(hwnd);
|
||
|
if (0 != ((WS_EX_STATICEDGE | WS_EX_CLIENTEDGE) & style))
|
||
|
return TRUE;
|
||
|
|
||
|
style = GetWindowStyle(hwnd);
|
||
|
if (0 != (WS_BORDER & style))
|
||
|
return TRUE;
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
static BOOL
|
||
|
EmbdeddedEditor_DrawBorder(EmbeddedEditor *self, HWND hwnd, HDC hdc)
|
||
|
{
|
||
|
RECT windowRect, clientRect;
|
||
|
HRGN borderRgn;
|
||
|
POINT polygons[16] = {0};
|
||
|
const int polygonsPointCount[] = {4, 4, 4, 4};
|
||
|
|
||
|
if (FALSE == GetWindowRect(hwnd, &windowRect) ||
|
||
|
FALSE == GetClientRect(hwnd, &clientRect))
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
MapWindowPoints(hwnd, HWND_DESKTOP, (POINT*)&clientRect, 2);
|
||
|
|
||
|
OffsetRect(&clientRect, -windowRect.left, -windowRect.top);
|
||
|
OffsetRect(&windowRect, -windowRect.left, -windowRect.top);
|
||
|
|
||
|
MakeRectPolygon(&polygons[0], windowRect.left, windowRect.top, windowRect.right, clientRect.top);
|
||
|
MakeRectPolygon(&polygons[4], clientRect.right, clientRect.top, windowRect.right, clientRect.bottom);
|
||
|
MakeRectPolygon(&polygons[8], windowRect.left, clientRect.bottom, windowRect.right, windowRect.bottom);
|
||
|
MakeRectPolygon(&polygons[12], windowRect.left, clientRect.top, clientRect.left, clientRect.bottom);
|
||
|
|
||
|
borderRgn = CreatePolyPolygonRgn(polygons,
|
||
|
polygonsPointCount,
|
||
|
ARRAYSIZE(polygonsPointCount),
|
||
|
WINDING);
|
||
|
|
||
|
if (NULL != borderRgn)
|
||
|
{
|
||
|
MakeRectPolygon(&polygons[0],
|
||
|
windowRect.left + EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_LEFT,
|
||
|
windowRect.top + EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_TOP,
|
||
|
windowRect.right - EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_RIGHT,
|
||
|
windowRect.top + (EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_TOP + EMBEDDEDEDITOR_FRAME_TOP));
|
||
|
MakeRectPolygon(&polygons[4],
|
||
|
windowRect.right - (EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_RIGHT + EMBEDDEDEDITOR_FRAME_RIGHT),
|
||
|
windowRect.top + (EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_TOP + EMBEDDEDEDITOR_FRAME_TOP),
|
||
|
windowRect.right - EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_RIGHT,
|
||
|
windowRect.bottom - (EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_BOTTOM + EMBEDDEDEDITOR_FRAME_BOTTOM));
|
||
|
MakeRectPolygon(&polygons[8],
|
||
|
windowRect.left + EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_LEFT,
|
||
|
windowRect.bottom - (EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_BOTTOM + EMBEDDEDEDITOR_FRAME_BOTTOM),
|
||
|
windowRect.right - EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_RIGHT,
|
||
|
windowRect.bottom - EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_BOTTOM);
|
||
|
MakeRectPolygon(&polygons[12],
|
||
|
windowRect.left + EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_LEFT,
|
||
|
windowRect.top + (EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_TOP + EMBEDDEDEDITOR_FRAME_TOP),
|
||
|
windowRect.left + (EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_LEFT + EMBEDDEDEDITOR_FRAME_LEFT),
|
||
|
windowRect.bottom - (EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_BOTTOM + EMBEDDEDEDITOR_FRAME_BOTTOM));
|
||
|
|
||
|
HRGN frameRgn = CreatePolyPolygonRgn(polygons,
|
||
|
polygonsPointCount,
|
||
|
ARRAYSIZE(polygonsPointCount),
|
||
|
WINDING);
|
||
|
if (NULL != frameRgn)
|
||
|
{
|
||
|
int combineResult = CombineRgn(frameRgn, borderRgn, frameRgn, RGN_AND);
|
||
|
if (NULLREGION != combineResult && ERROR != combineResult)
|
||
|
{
|
||
|
FillRgn(hdc, frameRgn, EmbeddedEditor_GetBorderBrush(self));
|
||
|
combineResult = CombineRgn(borderRgn, borderRgn, frameRgn, RGN_DIFF);
|
||
|
}
|
||
|
else
|
||
|
combineResult = COMPLEXREGION;
|
||
|
|
||
|
if (NULLREGION != combineResult && ERROR != combineResult)
|
||
|
FillRgn(hdc, borderRgn, EmbeddedEditor_GetBackBrush(self));
|
||
|
|
||
|
DeleteObject(frameRgn);
|
||
|
}
|
||
|
DeleteObject(borderRgn);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
static BOOL
|
||
|
EmbeddedEditor_InvokeCallback(EmbeddedEditor *self, HWND hwnd, BOOL cancelMode, BOOL removeCallback)
|
||
|
{
|
||
|
wchar_t *text;
|
||
|
unsigned int length;
|
||
|
EmbeddedEditorFinishCb callback;
|
||
|
|
||
|
if (NULL == self || NULL == self->callback)
|
||
|
return FALSE;
|
||
|
|
||
|
|
||
|
length = (unsigned int)SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0L);
|
||
|
text = String_Malloc(++length);
|
||
|
if (NULL == text)
|
||
|
return FALSE;
|
||
|
|
||
|
SendMessage(hwnd, WM_GETTEXT, (WPARAM)length, (LPARAM)text);
|
||
|
|
||
|
callback = self->callback;
|
||
|
if (FALSE != removeCallback)
|
||
|
self->callback = NULL;
|
||
|
|
||
|
callback(hwnd, cancelMode, text, self->user);
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
static const wchar_t *
|
||
|
EmbeddedEditor_GetWindowText(EmbeddedEditor *self, HWND hwnd, size_t *lengthOut)
|
||
|
{
|
||
|
size_t length;
|
||
|
|
||
|
length = (size_t)SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0L);
|
||
|
if (length >= self->bufferSize)
|
||
|
{
|
||
|
size_t size;
|
||
|
|
||
|
size = (((length + 1)/128) + 1) * 128;
|
||
|
|
||
|
String_Free(self->buffer);
|
||
|
self->buffer = String_Malloc(size);
|
||
|
if (NULL == self->buffer)
|
||
|
return FALSE;
|
||
|
|
||
|
self->bufferSize = size;
|
||
|
}
|
||
|
|
||
|
if (0 != length)
|
||
|
length = SendMessage(hwnd, WM_GETTEXT, (WPARAM)self->bufferSize, (LPARAM)self->buffer);
|
||
|
else
|
||
|
self->buffer[0] = L'\0';
|
||
|
|
||
|
if (NULL != lengthOut)
|
||
|
*lengthOut = length;
|
||
|
|
||
|
return self->buffer;
|
||
|
}
|
||
|
|
||
|
static BOOL
|
||
|
EmbeddedEditor_Resize(EmbeddedEditor *self, HWND hwnd, BOOL redraw)
|
||
|
{
|
||
|
size_t textLength;
|
||
|
const wchar_t *text;
|
||
|
HDC hdc;
|
||
|
SIZE maximumSize;
|
||
|
BOOL borderEnabled;
|
||
|
HWND parentWindow;
|
||
|
RECT rect, parentRect, marginRect;
|
||
|
SIZE parentSize;
|
||
|
BOOL result;
|
||
|
unsigned int windowStyle;
|
||
|
HFONT font, prevFont;
|
||
|
|
||
|
parentWindow = GetAncestor(hwnd, GA_PARENT);
|
||
|
if (NULL == parentWindow ||
|
||
|
FALSE == GetClientRect(parentWindow, &parentRect))
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
parentSize.cx = RECTWIDTH(parentRect);
|
||
|
parentSize.cy = RECTHEIGHT(parentRect);
|
||
|
|
||
|
windowStyle = GetWindowStyle(hwnd);
|
||
|
borderEnabled = EmbdeddedEditor_GetBorderEnabled(hwnd);
|
||
|
|
||
|
text = EmbeddedEditor_GetWindowText(self, hwnd, &textLength);
|
||
|
if (NULL == text)
|
||
|
return FALSE;
|
||
|
|
||
|
hdc = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS);
|
||
|
if (NULL == hdc)
|
||
|
return FALSE;
|
||
|
|
||
|
result = FALSE;
|
||
|
|
||
|
font = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0L);
|
||
|
prevFont = SelectFont(hdc, font);
|
||
|
|
||
|
if (-1 == self->spacing ||
|
||
|
-1 == self->lineHeight)
|
||
|
{
|
||
|
TEXTMETRIC textMetrics;
|
||
|
if (FALSE != GetTextMetrics(hdc, &textMetrics))
|
||
|
{
|
||
|
self->spacing = textMetrics.tmAveCharWidth;
|
||
|
self->lineHeight = textMetrics.tmHeight;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (0 == (ES_MULTILINE & windowStyle))
|
||
|
{
|
||
|
unsigned long margins;
|
||
|
margins = (unsigned long)SendMessage(hwnd, EM_GETMARGINS, 0, 0L);
|
||
|
SetRect(&marginRect, (short)LOWORD(margins), 0, (short)HIWORD(margins), 0);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
RECT clientRect;
|
||
|
if (FALSE == GetClientRect(hwnd, &clientRect))
|
||
|
SetRectEmpty(&clientRect);
|
||
|
|
||
|
if (clientRect.right < clientRect.left)
|
||
|
clientRect.right = clientRect.left;
|
||
|
if (clientRect.bottom < (clientRect.top + self->lineHeight))
|
||
|
clientRect.bottom = clientRect.top + self->lineHeight;
|
||
|
|
||
|
SendMessage(hwnd, EM_GETRECT, 0, (LPARAM)&marginRect);
|
||
|
|
||
|
marginRect.left = (marginRect.left > clientRect.left) ?
|
||
|
(marginRect.left - clientRect.left) : 1;
|
||
|
|
||
|
marginRect.top = (marginRect.top > clientRect.top) ?
|
||
|
(marginRect.top - clientRect.top) : 1;
|
||
|
|
||
|
marginRect.right = (marginRect.right < clientRect.right) ?
|
||
|
(clientRect.right - marginRect.right) : 1;
|
||
|
|
||
|
marginRect.bottom = (marginRect.bottom < clientRect.bottom) ?
|
||
|
(clientRect.bottom - marginRect.bottom) : 1;
|
||
|
|
||
|
if (SendMessage(hwnd, EM_GETLINECOUNT, 0, 0L) > 1)
|
||
|
{
|
||
|
if (marginRect.bottom >= (self->lineHeight - 1))
|
||
|
marginRect.bottom -= (self->lineHeight - 2);
|
||
|
}
|
||
|
|
||
|
SetRect(&marginRect, EMBEDDEDEDITOR_MARGIN_LEFT, EMBEDDEDEDITOR_MARGIN_TOP,
|
||
|
EMBEDDEDEDITOR_MARGIN_RIGHT, EMBEDDEDEDITOR_MARGIN_BOTTOM);
|
||
|
}
|
||
|
|
||
|
maximumSize.cx = (self->maximumSize.cx > 0) ? MIN(parentSize.cx, self->maximumSize.cx) : parentSize.cx;
|
||
|
maximumSize.cx -= (marginRect.left + marginRect.right);
|
||
|
if (FALSE != borderEnabled)
|
||
|
maximumSize.cx -= (EMBEDDEDEDITOR_BORDER_LEFT + EMBEDDEDEDITOR_BORDER_RIGHT);
|
||
|
|
||
|
if (maximumSize.cx < 0)
|
||
|
maximumSize.cx = 0;
|
||
|
|
||
|
maximumSize.cy = (self->maximumSize.cy > 0) ? MIN(parentSize.cy, self->maximumSize.cy) : parentSize.cy;
|
||
|
maximumSize.cy -= (marginRect.top + marginRect.bottom);
|
||
|
if (FALSE != borderEnabled)
|
||
|
maximumSize.cy -= (EMBEDDEDEDITOR_BORDER_TOP + EMBEDDEDEDITOR_BORDER_BOTTOM);
|
||
|
|
||
|
if (maximumSize.cy < 0)
|
||
|
maximumSize.cy = 0;
|
||
|
|
||
|
if (0 == textLength)
|
||
|
{
|
||
|
SetRectEmpty(&rect);
|
||
|
result = TRUE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SetRect(&rect, 0, 0, maximumSize.cx, maximumSize.cy);
|
||
|
result = DrawText(hdc, text, (int)textLength, &rect,
|
||
|
DT_CALCRECT | DT_LEFT | DT_TOP | DT_WORDBREAK |
|
||
|
DT_EDITCONTROL | DT_NOPREFIX);
|
||
|
}
|
||
|
|
||
|
SelectFont(hdc, prevFont);
|
||
|
ReleaseDC(hwnd, hdc);
|
||
|
|
||
|
|
||
|
if (FALSE != result)
|
||
|
{
|
||
|
unsigned int flags;
|
||
|
|
||
|
rect.right += 2 * self->spacing;
|
||
|
|
||
|
if (RECTHEIGHT(rect) < self->lineHeight)
|
||
|
rect.bottom = rect.top + self->lineHeight;
|
||
|
else if (RECTHEIGHT(rect) > self->lineHeight)
|
||
|
rect.right = rect.left + maximumSize.cx;
|
||
|
|
||
|
rect.right += (marginRect.left + marginRect.right);
|
||
|
rect.bottom += (marginRect.top + marginRect.bottom);
|
||
|
|
||
|
if (FALSE != borderEnabled)
|
||
|
{
|
||
|
rect.right += (EMBEDDEDEDITOR_BORDER_LEFT + EMBEDDEDEDITOR_BORDER_RIGHT);
|
||
|
rect.bottom += (EMBEDDEDEDITOR_BORDER_TOP + EMBEDDEDEDITOR_BORDER_BOTTOM);
|
||
|
}
|
||
|
|
||
|
flags = SWP_NOACTIVATE | SWP_NOZORDER;
|
||
|
if (FALSE == redraw)
|
||
|
flags |= SWP_NOREDRAW;
|
||
|
|
||
|
OffsetRect(&rect, self->anchorPoint.x, self->anchorPoint.y);
|
||
|
|
||
|
long offsetX = 0, offsetY = 0;
|
||
|
|
||
|
if (0 != (ES_CENTER & windowStyle))
|
||
|
{
|
||
|
if (self->maximumSize.cx > 0)
|
||
|
{
|
||
|
offsetX += (self->maximumSize.cx - RECTWIDTH(rect))/2;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (rect.right > parentSize.cx)
|
||
|
offsetX -= (rect.right - parentSize.cx);
|
||
|
|
||
|
if (rect.bottom > parentSize.cy)
|
||
|
offsetY -= (rect.bottom - parentSize.cy);
|
||
|
|
||
|
OffsetRect(&rect, offsetX, offsetY);
|
||
|
|
||
|
result = SetWindowPos(hwnd, NULL, rect.left, rect.top, RECTWIDTH(rect), RECTHEIGHT(rect), flags);
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
EmbdeddedEditor_OnDestroy(EmbeddedEditor *self, HWND hwnd)
|
||
|
{
|
||
|
HWND parent;
|
||
|
|
||
|
if (NULL != self &&
|
||
|
NULL != self->callback)
|
||
|
{
|
||
|
EmbeddedEditor_InvokeCallback(self, hwnd, TRUE, TRUE);
|
||
|
}
|
||
|
|
||
|
RemoveProp(hwnd, MAKEINTATOM(EMBEDDEDEDITOR_PROP));
|
||
|
if (NULL == self)
|
||
|
return;
|
||
|
|
||
|
if (NULL != self->originalProc)
|
||
|
{
|
||
|
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)self->originalProc);
|
||
|
CallWindowProc(self->originalProc, hwnd, WM_DESTROY, 0, 0L);
|
||
|
}
|
||
|
|
||
|
if(NULL != self->backBrush)
|
||
|
DeleteObject(self->backBrush);
|
||
|
|
||
|
if (NULL != self->borderBrush)
|
||
|
DeleteObject(self->borderBrush);
|
||
|
|
||
|
String_Free(self->buffer);
|
||
|
|
||
|
free(self);
|
||
|
|
||
|
parent = GetAncestor(hwnd, GA_PARENT);
|
||
|
if(NULL != parent)
|
||
|
EmbeddedEditorParent_RemoveChild(parent, hwnd);
|
||
|
|
||
|
EmbeddidEditorThread_EndMouseMonitor(hwnd);
|
||
|
}
|
||
|
|
||
|
static BOOL
|
||
|
EmbdeddedEditor_OnNcCalcSize(EmbeddedEditor *self, HWND hwnd, BOOL calcValidRects,
|
||
|
NCCALCSIZE_PARAMS *params, LRESULT *result)
|
||
|
{
|
||
|
|
||
|
if (FALSE != EmbdeddedEditor_GetBorderEnabled(hwnd))
|
||
|
{
|
||
|
if (FALSE != calcValidRects)
|
||
|
{
|
||
|
SetRect(¶ms->rgrc[0],
|
||
|
params->lppos->x + EMBEDDEDEDITOR_BORDER_LEFT,
|
||
|
params->lppos->y + EMBEDDEDEDITOR_BORDER_TOP,
|
||
|
params->lppos->x + params->lppos->cx - EMBEDDEDEDITOR_BORDER_RIGHT,
|
||
|
params->lppos->y + params->lppos->cy - EMBEDDEDEDITOR_BORDER_BOTTOM);
|
||
|
|
||
|
*result = WVR_ALIGNTOP | WVR_ALIGNLEFT;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (FALSE != GetWindowRect(hwnd, ¶ms->rgrc[0]))
|
||
|
{
|
||
|
params->rgrc[0].left += EMBEDDEDEDITOR_BORDER_LEFT;
|
||
|
params->rgrc[0].top += EMBEDDEDEDITOR_BORDER_TOP;
|
||
|
params->rgrc[0].right -= EMBEDDEDEDITOR_BORDER_RIGHT;
|
||
|
params->rgrc[0].bottom -= EMBEDDEDEDITOR_BORDER_BOTTOM;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
static BOOL
|
||
|
EmbdeddedEditor_OnNcPaint(EmbeddedEditor *self, HWND hwnd, HRGN updateRegion)
|
||
|
{
|
||
|
BOOL result;
|
||
|
|
||
|
if (FALSE != EmbdeddedEditor_GetBorderEnabled(hwnd))
|
||
|
{
|
||
|
HDC hdc;
|
||
|
unsigned int flags;
|
||
|
|
||
|
flags = DCX_PARENTCLIP | DCX_CACHE | DCX_WINDOW | DCX_CLIPSIBLINGS |
|
||
|
DCX_INTERSECTUPDATE | DCX_VALIDATE;
|
||
|
|
||
|
hdc = GetDCEx(hwnd, ((HRGN)NULLREGION != updateRegion) ? updateRegion : NULL, flags);
|
||
|
if (NULL != hdc)
|
||
|
{
|
||
|
result = EmbdeddedEditor_DrawBorder(self, hwnd, hdc);
|
||
|
ReleaseDC(hwnd, hdc);
|
||
|
}
|
||
|
else
|
||
|
result = FALSE;
|
||
|
}
|
||
|
else
|
||
|
result = TRUE;
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
static BOOL
|
||
|
EmbeddedEditor_OnSetCursor(EmbeddedEditor *self, HWND hwnd, HWND cursorWindow, int hitTest, int mouseMessage, LRESULT *result)
|
||
|
{
|
||
|
HCURSOR cursor;
|
||
|
|
||
|
if (cursorWindow != hwnd ||
|
||
|
HTCLIENT != hitTest)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
cursor = LoadCursor(NULL, IDC_IBEAM);
|
||
|
if (NULL == cursor)
|
||
|
return FALSE;
|
||
|
|
||
|
SetCursor(cursor);
|
||
|
|
||
|
*result = TRUE;
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
static BOOL
|
||
|
EmbeddedEditor_OnGetDlgCode(EmbeddedEditor *self, HWND hwnd, unsigned int vKey, MSG *message, LRESULT *result)
|
||
|
{
|
||
|
if (NULL != message)
|
||
|
{
|
||
|
switch(vKey)
|
||
|
{
|
||
|
case VK_TAB:
|
||
|
case VK_ESCAPE:
|
||
|
EmbeddedEditor_InvokeCallback(self, hwnd, TRUE, TRUE);
|
||
|
DestroyWindow(hwnd);
|
||
|
*result = DLGC_WANTMESSAGE;
|
||
|
return TRUE;
|
||
|
case VK_RETURN:
|
||
|
EmbeddedEditor_InvokeCallback(self, hwnd, FALSE, TRUE);
|
||
|
DestroyWindow(hwnd);
|
||
|
*result = DLGC_WANTMESSAGE;
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (NULL != self->originalProc)
|
||
|
*result = CallWindowProc(self->originalProc, hwnd, WM_GETDLGCODE, (WPARAM)vKey, (LPARAM)message);
|
||
|
else
|
||
|
*result = 0;
|
||
|
|
||
|
if (NULL == message)
|
||
|
*result |= DLGC_WANTMESSAGE;
|
||
|
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
static BOOL
|
||
|
EmbeddedEditor_OnKillFocus(EmbeddedEditor *self, HWND hwnd, HWND focusedWindow)
|
||
|
{
|
||
|
EmbeddedEditor_InvokeCallback(self, hwnd, FALSE, TRUE);
|
||
|
DestroyWindow(hwnd);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
static BOOL
|
||
|
EmbeddedEditor_OnMouseWheel(EmbeddedEditor *self, HWND hwnd, int virtualKeys, int distance, long pointer_s)
|
||
|
{
|
||
|
HWND parentWindow;
|
||
|
|
||
|
parentWindow = GetAncestor(hwnd, GA_PARENT);
|
||
|
|
||
|
EmbeddedEditor_InvokeCallback(self, hwnd, TRUE, TRUE);
|
||
|
DestroyWindow(hwnd);
|
||
|
|
||
|
if (NULL != parentWindow)
|
||
|
{
|
||
|
SendMessage(parentWindow, WM_MOUSEWHEEL,
|
||
|
MAKEWPARAM(virtualKeys, distance), (LPARAM)pointer_s);
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
EmbeddedEditor_OnCommand(EmbeddedEditor *self, HWND hwnd, int eventId)
|
||
|
{
|
||
|
switch(eventId)
|
||
|
{
|
||
|
case EN_UPDATE:
|
||
|
EmbeddedEditor_Resize(self, hwnd, TRUE);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
static BOOL
|
||
|
EmbeddedEditor_OnSetFont(EmbeddedEditor *self, HWND hwnd, HFONT font, BOOL redraw)
|
||
|
{
|
||
|
if (NULL != self->originalProc)
|
||
|
CallWindowProc(self->originalProc, hwnd, WM_SETFONT, (WPARAM)font, MAKELPARAM(redraw, 0));
|
||
|
|
||
|
self->spacing = -1;
|
||
|
self->lineHeight = -1;
|
||
|
|
||
|
EmbeddedEditor_Resize(self, hwnd, redraw);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
static BOOL
|
||
|
EmbeddedEditor_OnWindowPosChanged(EmbeddedEditor *self, HWND hwnd, WINDOWPOS *pwp)
|
||
|
{
|
||
|
if (SWP_NOSIZE != ((SWP_NOSIZE | SWP_FRAMECHANGED) & pwp->flags))
|
||
|
{
|
||
|
RECT formatRect;
|
||
|
if (FALSE != GetClientRect(hwnd, &formatRect))
|
||
|
{
|
||
|
formatRect.left += EMBEDDEDEDITOR_MARGIN_LEFT;
|
||
|
formatRect.top += EMBEDDEDEDITOR_MARGIN_TOP;
|
||
|
formatRect.right -= EMBEDDEDEDITOR_MARGIN_RIGHT;
|
||
|
formatRect.bottom -= EMBEDDEDEDITOR_MARGIN_BOTTOM;
|
||
|
|
||
|
if (formatRect.right < formatRect.left)
|
||
|
formatRect.right = formatRect.left;
|
||
|
|
||
|
if (formatRect.bottom < formatRect.top)
|
||
|
formatRect.bottom = formatRect.top;
|
||
|
|
||
|
SendMessage(hwnd, EM_SETRECTNP, 0, (LPARAM)&formatRect);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (NULL != self->originalProc)
|
||
|
CallWindowProc(self->originalProc, hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)pwp);
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
EmbeddedEditor_OnSetTextColor(EmbeddedEditor *self, HWND hwnd, COLORREF color, LRESULT *result)
|
||
|
{
|
||
|
*result = (LRESULT)self->textColor;
|
||
|
if (self->textColor != color)
|
||
|
self->textColor = color;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
EmbeddedEditor_OnGetTextColor(EmbeddedEditor *self, HWND hwnd, LRESULT *result)
|
||
|
{
|
||
|
*result = (LRESULT)self->textColor;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
EmbeddedEditor_OnSetBackColor(EmbeddedEditor *self, HWND hwnd, COLORREF color, LRESULT *result)
|
||
|
{
|
||
|
*result = (LRESULT)self->backColor;
|
||
|
if (self->backColor != color)
|
||
|
{
|
||
|
self->backColor = color;
|
||
|
if (NULL != self->backBrush)
|
||
|
{
|
||
|
DeleteObject(self->backBrush);
|
||
|
self->backBrush = NULL;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
EmbeddedEditor_OnGetBackColor(EmbeddedEditor *self, HWND hwnd, LRESULT *result)
|
||
|
{
|
||
|
*result = (LRESULT)self->backColor;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
EmbeddedEditor_OnSetBorderColor(EmbeddedEditor *self, HWND hwnd, COLORREF color, LRESULT *result)
|
||
|
{
|
||
|
*result = (LRESULT)self->borderColor;
|
||
|
if (self->borderColor != color)
|
||
|
{
|
||
|
self->borderColor = color;
|
||
|
if (NULL != self->borderBrush)
|
||
|
{
|
||
|
DeleteObject(self->borderBrush);
|
||
|
self->borderBrush = NULL;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
EmbeddedEditor_OnGetBorderColor(EmbeddedEditor *self, HWND hwnd, LRESULT *result)
|
||
|
{
|
||
|
*result = (LRESULT)self->borderColor;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
EmbeddedEditor_OnSetUserData(EmbeddedEditor *self, HWND hwnd, void *user, LRESULT *result)
|
||
|
{
|
||
|
*result = (LRESULT)self->user;
|
||
|
self->user = user;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
EmbeddedEditor_OnGetUserData(EmbeddedEditor *self, HWND hwnd, LRESULT *result)
|
||
|
{
|
||
|
*result = (LRESULT)self->user;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
EmbeddedEditor_OnSetAnchorPoint(EmbeddedEditor *self, HWND hwnd, long x, long y, LRESULT *result)
|
||
|
{
|
||
|
self->anchorPoint.x = x;
|
||
|
self->anchorPoint.y = y;
|
||
|
*result = TRUE;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
EmbeddedEditor_OnGetAnchorPoint(EmbeddedEditor *self, HWND hwnd, long *x, long *y, LRESULT *result)
|
||
|
{
|
||
|
if (NULL != x)
|
||
|
*x = self->anchorPoint.x;
|
||
|
|
||
|
if (NULL != y)
|
||
|
*y = self->anchorPoint.y;
|
||
|
|
||
|
*result = TRUE;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
EmbeddedEditor_OnSetMaxSize(EmbeddedEditor *self, HWND hwnd, long width, long height, LRESULT *result)
|
||
|
{
|
||
|
self->maximumSize.cx = width;
|
||
|
self->maximumSize.cy = height;
|
||
|
*result = TRUE;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
EmbeddedEditor_OnGetMaxSize(EmbeddedEditor *self, HWND hwnd, long *width, long *height, LRESULT *result)
|
||
|
{
|
||
|
if (NULL != width)
|
||
|
*width = self->maximumSize.cx;
|
||
|
|
||
|
if (NULL != height)
|
||
|
*height = self->maximumSize.cy;
|
||
|
|
||
|
*result = TRUE;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
EmbeddedEditor_OnEndEditing(EmbeddedEditor *self, HWND hwnd, BOOL cancel)
|
||
|
{
|
||
|
EmbeddedEditor_InvokeCallback(self, hwnd, cancel, TRUE);
|
||
|
DestroyWindow(hwnd);
|
||
|
}
|
||
|
|
||
|
static BOOL
|
||
|
EmbeddedEditor_MessageProc(EmbeddedEditor *self, HWND hwnd, UINT uMsg,
|
||
|
WPARAM wParam, LPARAM lParam, LRESULT *result)
|
||
|
{
|
||
|
|
||
|
switch(uMsg)
|
||
|
{
|
||
|
case WM_DESTROY:
|
||
|
EmbdeddedEditor_OnDestroy(self, hwnd);
|
||
|
return TRUE;
|
||
|
case WM_NCCALCSIZE:
|
||
|
return EmbdeddedEditor_OnNcCalcSize(self, hwnd, (BOOL)wParam, (NCCALCSIZE_PARAMS*)lParam, result);
|
||
|
case WM_NCPAINT:
|
||
|
return EmbdeddedEditor_OnNcPaint(self, hwnd, (HRGN)wParam);
|
||
|
case WM_SETCURSOR:
|
||
|
return EmbeddedEditor_OnSetCursor(self, hwnd, (HWND)wParam,
|
||
|
LOWORD(lParam), HIWORD(lParam), result);
|
||
|
case WM_GETDLGCODE:
|
||
|
return EmbeddedEditor_OnGetDlgCode(self, hwnd, (unsigned int)wParam, (MSG*)lParam, result);
|
||
|
case WM_KILLFOCUS:
|
||
|
EmbeddedEditor_OnKillFocus(self, hwnd, (HWND)wParam);
|
||
|
return 0;
|
||
|
case WM_MOUSEWHEEL:
|
||
|
return EmbeddedEditor_OnMouseWheel(self, hwnd, LOWORD(wParam), (short)HIWORD(wParam), (LONG)lParam);
|
||
|
case WM_SETFONT:
|
||
|
return EmbeddedEditor_OnSetFont(self, hwnd, (HFONT)wParam, (BOOL)LOWORD(lParam));
|
||
|
case WM_WINDOWPOSCHANGED:
|
||
|
return EmbeddedEditor_OnWindowPosChanged(self, hwnd, (WINDOWPOS*)lParam);
|
||
|
|
||
|
case EMBEDDEDEDITOR_WM_SET_TEXT_COLOR: EmbeddedEditor_OnSetTextColor(self, hwnd, (COLORREF)lParam, result); return TRUE;
|
||
|
case EMBEDDEDEDITOR_WM_GET_TEXT_COLOR: EmbeddedEditor_OnGetTextColor(self, hwnd, result); return TRUE;
|
||
|
case EMBEDDEDEDITOR_WM_SET_BACK_COLOR: EmbeddedEditor_OnSetBackColor(self, hwnd, (COLORREF)lParam, result); return TRUE;
|
||
|
case EMBEDDEDEDITOR_WM_GET_BACK_COLOR: EmbeddedEditor_OnGetBackColor(self, hwnd, result); return TRUE;
|
||
|
case EMBEDDEDEDITOR_WM_SET_BORDER_COLOR: EmbeddedEditor_OnSetBorderColor(self, hwnd, (COLORREF)lParam, result); return TRUE;
|
||
|
case EMBEDDEDEDITOR_WM_GET_BORDER_COLOR: EmbeddedEditor_OnGetBorderColor(self, hwnd, result); return TRUE;
|
||
|
case EMBEDDEDEDITOR_WM_SET_USER_DATA: EmbeddedEditor_OnSetUserData(self, hwnd, (void*)lParam, result); return TRUE;
|
||
|
case EMBEDDEDEDITOR_WM_GET_USER_DATA: EmbeddedEditor_OnGetUserData(self, hwnd, result); return TRUE;
|
||
|
case EMBEDDEDEDITOR_WM_SET_ANCHOR_POINT: EmbeddedEditor_OnSetAnchorPoint(self, hwnd, (long)wParam, (long)lParam, result); return TRUE;
|
||
|
case EMBEDDEDEDITOR_WM_GET_ANCHOR_POINT: EmbeddedEditor_OnGetAnchorPoint(self, hwnd, (long*)wParam, (long*)lParam, result); return TRUE;
|
||
|
case EMBEDDEDEDITOR_WM_SET_MAX_SIZE: EmbeddedEditor_OnSetMaxSize(self, hwnd, (long)wParam, (long)lParam, result); return TRUE;
|
||
|
case EMBEDDEDEDITOR_WM_GET_MAX_SIZE: EmbeddedEditor_OnGetMaxSize(self, hwnd, (long*)wParam, (long*)lParam, result); return TRUE;
|
||
|
case EMBEDDEDEDITOR_WM_END_EDITING: EmbeddedEditor_OnEndEditing(self, hwnd, (BOOL)wParam); return TRUE;
|
||
|
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
static LRESULT WINAPI
|
||
|
EmbeddedEditor_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
EmbeddedEditor *self;
|
||
|
LRESULT result;
|
||
|
|
||
|
self = EMBEDDEDEDITOR(hwnd);
|
||
|
|
||
|
if (NULL == self ||
|
||
|
NULL == self->originalProc)
|
||
|
{
|
||
|
return DefWindowProc(hwnd, uMsg, wParam, lParam);
|
||
|
}
|
||
|
|
||
|
result = 0;
|
||
|
if (FALSE != EmbeddedEditor_MessageProc(self, hwnd, uMsg, wParam, lParam, &result))
|
||
|
{
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
return CallWindowProc(self->originalProc, hwnd, uMsg, wParam, lParam);
|
||
|
}
|
||
|
|
||
|
|
||
|
static void
|
||
|
EmbdeddedEditorParent_OnDestroy(EmbeddedEditorParent *self, HWND hwnd)
|
||
|
{
|
||
|
RemoveProp(hwnd, MAKEINTATOM(EMBEDDEDEDITOR_PROP));
|
||
|
if (NULL == self)
|
||
|
return;
|
||
|
|
||
|
if (NULL != self->originalProc)
|
||
|
{
|
||
|
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)self->originalProc);
|
||
|
CallWindowProc(self->originalProc, hwnd, WM_DESTROY, 0, 0L);
|
||
|
}
|
||
|
|
||
|
delete self;
|
||
|
}
|
||
|
|
||
|
static BOOL
|
||
|
EmbdeddedEditorParent_OnGetEditColors(EmbeddedEditorParent *self, HWND hwnd, HDC hdc, HWND control, LRESULT *result)
|
||
|
{
|
||
|
size_t index;
|
||
|
index = self->editorList.size();
|
||
|
while(index--)
|
||
|
{
|
||
|
if (control == self->editorList[index])
|
||
|
{
|
||
|
EmbeddedEditor *editor = EMBEDDEDEDITOR(control);
|
||
|
if (NULL != editor)
|
||
|
{
|
||
|
SetTextColor(hdc, editor->textColor);
|
||
|
SetBkColor(hdc, editor->backColor);
|
||
|
*result = (LRESULT)EmbeddedEditor_GetBackBrush(editor);
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
EmbdeddedEditorParent_OnCommand(EmbeddedEditorParent *self, HWND hwnd, int commandId, int eventId, HWND control)
|
||
|
{
|
||
|
size_t index;
|
||
|
|
||
|
if (NULL == control)
|
||
|
return;
|
||
|
|
||
|
index = self->editorList.size();
|
||
|
while(index--)
|
||
|
{
|
||
|
if (control == self->editorList[index])
|
||
|
{
|
||
|
EmbeddedEditor *editor = EMBEDDEDEDITOR(control);
|
||
|
if (NULL != editor)
|
||
|
{
|
||
|
EmbeddedEditor_OnCommand(editor, control, eventId);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
static BOOL
|
||
|
EmbeddedEditorParent_MessageProc(EmbeddedEditorParent *self, HWND hwnd, UINT uMsg,
|
||
|
WPARAM wParam, LPARAM lParam, LRESULT *result)
|
||
|
{
|
||
|
|
||
|
switch(uMsg)
|
||
|
{
|
||
|
case WM_DESTROY:
|
||
|
EmbdeddedEditorParent_OnDestroy(self, hwnd);
|
||
|
return TRUE;
|
||
|
|
||
|
case WM_CTLCOLOREDIT:
|
||
|
return EmbdeddedEditorParent_OnGetEditColors(self, hwnd, (HDC)wParam, (HWND)lParam, result);
|
||
|
|
||
|
case WM_COMMAND:
|
||
|
EmbdeddedEditorParent_OnCommand(self, hwnd, LOWORD(wParam), HIWORD(wParam), (HWND)lParam);
|
||
|
break;
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
static LRESULT WINAPI
|
||
|
EmbeddedEditorParent_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
EmbeddedEditorParent *self;
|
||
|
LRESULT result;
|
||
|
|
||
|
self = EMBEDDEDEDITOR_PARENT(hwnd);
|
||
|
|
||
|
if (NULL == self ||
|
||
|
NULL == self->originalProc)
|
||
|
{
|
||
|
return DefWindowProc(hwnd, uMsg, wParam, lParam);
|
||
|
}
|
||
|
|
||
|
result = 0;
|
||
|
if (FALSE != EmbeddedEditorParent_MessageProc(self, hwnd, uMsg, wParam, lParam, &result))
|
||
|
{
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
return CallWindowProc(self->originalProc, hwnd, uMsg, wParam, lParam);
|
||
|
}
|
||
|
|
||
|
|
||
|
static LRESULT CALLBACK
|
||
|
EmbeddidEditorThread_MouseProc(int code, unsigned int messageId, MOUSEHOOKSTRUCT *mouse)
|
||
|
{
|
||
|
if ((size_t)-1 != editorTls)
|
||
|
{
|
||
|
EmbeddedEditorThread *threadData;
|
||
|
threadData = (EmbeddedEditorThread*)WASABI_API_APP->GetThreadStorage(editorTls);
|
||
|
|
||
|
if (NULL != threadData)
|
||
|
{
|
||
|
LRESULT result;
|
||
|
if (NULL != threadData->hook)
|
||
|
result = CallNextHookEx(threadData->hook, code, (WPARAM)messageId, (LPARAM)mouse);
|
||
|
else
|
||
|
result = 0;
|
||
|
|
||
|
if (code >= 0)
|
||
|
{
|
||
|
if ((messageId >= WM_LBUTTONDOWN && messageId <= 0x20E && mouse->hwnd != threadData->window) ||
|
||
|
(messageId >= WM_NCLBUTTONDOWN && messageId <= 0x00AD))
|
||
|
{
|
||
|
|
||
|
HWND editorWindow;
|
||
|
editorWindow = threadData->window;
|
||
|
if (NULL != editorWindow)
|
||
|
PostMessage(editorWindow, EMBEDDEDEDITOR_WM_END_EDITING, FALSE, 0L);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|