📄 scintillawin.cxx
字号:
::CloseClipboard();
}
void ScintillaWin::ScrollMessage(WPARAM wParam) {
//DWORD dwStart = timeGetTime();
//Platform::DebugPrintf("Scroll %x %d\n", wParam, lParam);
SCROLLINFO sci;
memset(&sci, 0, sizeof(sci));
sci.cbSize = sizeof(sci);
sci.fMask = SIF_ALL;
::GetScrollInfo(MainHWND(), SB_VERT, &sci);
//Platform::DebugPrintf("ScrollInfo %d mask=%x min=%d max=%d page=%d pos=%d track=%d\n", b,sci.fMask,
//sci.nMin, sci.nMax, sci.nPage, sci.nPos, sci.nTrackPos);
int topLineNew = topLine;
switch (LoWord(wParam)) {
case SB_LINEUP:
topLineNew -= 1;
break;
case SB_LINEDOWN:
topLineNew += 1;
break;
case SB_PAGEUP:
topLineNew -= LinesToScroll(); break;
case SB_PAGEDOWN: topLineNew += LinesToScroll(); break;
case SB_TOP: topLineNew = 0; break;
case SB_BOTTOM: topLineNew = MaxScrollPos(); break;
case SB_THUMBPOSITION: topLineNew = sci.nTrackPos; break;
case SB_THUMBTRACK: topLineNew = sci.nTrackPos; break;
}
ScrollTo(topLineNew);
}
void ScintillaWin::HorizontalScrollMessage(WPARAM wParam) {
int xPos = xOffset;
PRectangle rcText = GetTextRectangle();
int pageWidth = rcText.Width() * 2 / 3;
switch (LoWord(wParam)) {
case SB_LINEUP:
xPos -= 20;
break;
case SB_LINEDOWN: // May move past the logical end
xPos += 20;
break;
case SB_PAGEUP:
xPos -= pageWidth;
break;
case SB_PAGEDOWN:
xPos += pageWidth;
if (xPos > scrollWidth - rcText.Width()) { // Hit the end exactly
xPos = scrollWidth - rcText.Width();
}
break;
case SB_TOP:
xPos = 0;
break;
case SB_BOTTOM:
xPos = scrollWidth;
break;
case SB_THUMBPOSITION:
xPos = HiWord(wParam);
break;
case SB_THUMBTRACK:
xPos = HiWord(wParam);
break;
}
HorizontalScrollTo(xPos);
}
void ScintillaWin::RealizeWindowPalette(bool inBackGround) {
RefreshStyleData();
HDC hdc = ::GetDC(MainHWND());
AutoSurface surfaceWindow(hdc, this);
if (surfaceWindow) {
int changes = surfaceWindow->SetPalette(&palette, inBackGround);
if (changes > 0)
Redraw();
surfaceWindow->Release();
}
::ReleaseDC(MainHWND(), hdc);
}
/**
* Redraw all of text area.
* This paint will not be abandoned.
*/
void ScintillaWin::FullPaint() {
paintState = painting;
rcPaint = GetClientRectangle();
paintingAllText = true;
HDC hdc = ::GetDC(MainHWND());
AutoSurface surfaceWindow(hdc, this);
if (surfaceWindow) {
Paint(surfaceWindow, rcPaint);
surfaceWindow->Release();
}
::ReleaseDC(MainHWND(), hdc);
paintState = notPainting;
}
/// Implement IUnknown
STDMETHODIMP ScintillaWin::QueryInterface(REFIID riid, PVOID *ppv) {
*ppv = NULL;
if (riid == IID_IUnknown)
*ppv = reinterpret_cast<IDropTarget *>(&dt);
if (riid == IID_IDropSource)
*ppv = reinterpret_cast<IDropSource *>(&ds);
if (riid == IID_IDropTarget)
*ppv = reinterpret_cast<IDropTarget *>(&dt);
if (riid == IID_IDataObject)
*ppv = reinterpret_cast<IDataObject *>(&dob);
if (!*ppv)
return E_NOINTERFACE;
return S_OK;
}
STDMETHODIMP_(ULONG) ScintillaWin::AddRef() {
return 1;
}
STDMETHODIMP_(ULONG) ScintillaWin::Release() {
return 1;
}
/// Implement IDropTarget
STDMETHODIMP ScintillaWin::DragEnter(LPDATAOBJECT pIDataSource, DWORD grfKeyState,
POINTL, PDWORD pdwEffect) {
if (pIDataSource == NULL)
return E_POINTER;
if (IsUnicodeMode()) {
FORMATETC fmtu = {CF_UNICODETEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
HRESULT hrHasUText = pIDataSource->QueryGetData(&fmtu);
hasOKText = (hrHasUText == S_OK);
}
if (!hasOKText) {
FORMATETC fmte = {CF_TEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
HRESULT hrHasText = pIDataSource->QueryGetData(&fmte);
hasOKText = (hrHasText == S_OK);
}
if (!hasOKText) {
*pdwEffect = DROPEFFECT_NONE;
return S_OK;
}
if (inDragDrop) // Internal defaults to move
*pdwEffect = DROPEFFECT_MOVE;
else
*pdwEffect = DROPEFFECT_COPY;
if (grfKeyState & MK_ALT)
*pdwEffect = DROPEFFECT_MOVE;
if (grfKeyState & MK_CONTROL)
*pdwEffect = DROPEFFECT_COPY;
return S_OK;
}
STDMETHODIMP ScintillaWin::DragOver(DWORD grfKeyState, POINTL pt, PDWORD pdwEffect) {
if (!hasOKText || pdoc->IsReadOnly()) {
*pdwEffect = DROPEFFECT_NONE;
return S_OK;
}
// These are the Wordpad semantics.
if (inDragDrop) // Internal defaults to move
*pdwEffect = DROPEFFECT_MOVE;
else
*pdwEffect = DROPEFFECT_COPY;
if (grfKeyState & MK_ALT)
*pdwEffect = DROPEFFECT_MOVE;
if (grfKeyState & MK_CONTROL)
*pdwEffect = DROPEFFECT_COPY;
// Update the cursor.
POINT rpt = {pt.x, pt.y};
::ScreenToClient(MainHWND(), &rpt);
SetDragPosition(PositionFromLocation(Point(rpt.x, rpt.y)));
return S_OK;
}
STDMETHODIMP ScintillaWin::DragLeave() {
SetDragPosition(invalidPosition);
return S_OK;
}
STDMETHODIMP ScintillaWin::Drop(LPDATAOBJECT pIDataSource, DWORD grfKeyState,
POINTL pt, PDWORD pdwEffect) {
if (inDragDrop) // Internal defaults to move
*pdwEffect = DROPEFFECT_MOVE;
else
*pdwEffect = DROPEFFECT_COPY;
if (grfKeyState & MK_ALT)
*pdwEffect = DROPEFFECT_MOVE;
if (grfKeyState & MK_CONTROL)
*pdwEffect = DROPEFFECT_COPY;
if (pIDataSource == NULL)
return E_POINTER;
SetDragPosition(invalidPosition);
STGMEDIUM medium={0,{0},0};
HRESULT hr = S_OK;
char *data = 0;
bool dataAllocated = false;
if (IsUnicodeMode()) {
FORMATETC fmtu = {CF_UNICODETEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
hr = pIDataSource->GetData(&fmtu, &medium);
if (SUCCEEDED(hr) && medium.hGlobal) {
wchar_t *udata = static_cast<wchar_t *>(::GlobalLock(medium.hGlobal));
int tlen = ::GlobalSize(medium.hGlobal);
// Convert UCS-2 to UTF-8
int dataLen = UTF8Length(udata, tlen/2);
data = new char[dataLen+1];
if (data) {
UTF8FromUCS2(udata, tlen/2, data, dataLen);
dataAllocated = true;
}
}
}
if (!data) {
FORMATETC fmte = {CF_TEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
hr = pIDataSource->GetData(&fmte, &medium);
if (SUCCEEDED(hr) && medium.hGlobal) {
data = static_cast<char *>(::GlobalLock(medium.hGlobal));
}
}
if (!data) {
//Platform::DebugPrintf("Bad data format: 0x%x\n", hres);
return hr;
}
FORMATETC fmtr = {cfColumnSelect, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
HRESULT hrRectangular = pIDataSource->QueryGetData(&fmtr);
POINT rpt = {pt.x, pt.y};
::ScreenToClient(MainHWND(), &rpt);
int movePos = PositionFromLocation(Point(rpt.x, rpt.y));
DropAt(movePos, data, *pdwEffect == DROPEFFECT_MOVE, hrRectangular == S_OK);
::GlobalUnlock(medium.hGlobal);
// Free data
if (medium.pUnkForRelease != NULL)
medium.pUnkForRelease->Release();
else
::GlobalFree(medium.hGlobal);
if (dataAllocated)
delete []data;
return S_OK;
}
/// Implement important part of IDataObject
STDMETHODIMP ScintillaWin::GetData(FORMATETC *pFEIn, STGMEDIUM *pSTM) {
bool formatOK = (pFEIn->cfFormat == CF_TEXT) ||
((pFEIn->cfFormat == CF_UNICODETEXT) && IsUnicodeMode()) ||
(pFEIn->cfFormat == CF_HDROP);
if (!formatOK ||
pFEIn->ptd != 0 ||
(pFEIn->dwAspect & DVASPECT_CONTENT) == 0 ||
pFEIn->lindex != -1 ||
(pFEIn->tymed & TYMED_HGLOBAL) == 0
) {
//Platform::DebugPrintf("DOB GetData No %d %x %x fmt=%x\n", lenDrag, pFEIn, pSTM, pFEIn->cfFormat);
return DATA_E_FORMATETC;
}
pSTM->tymed = TYMED_HGLOBAL;
if (pFEIn->cfFormat == CF_HDROP) {
pSTM->hGlobal = 0;
pSTM->pUnkForRelease = 0;
return S_OK;
}
//Platform::DebugPrintf("DOB GetData OK %d %x %x\n", lenDrag, pFEIn, pSTM);
HGLOBAL hand;
if (pFEIn->cfFormat == CF_UNICODETEXT) {
int uchars = UCS2Length(drag.s, drag.len);
hand = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, 2 * (uchars + 1));
if (hand) {
wchar_t *uptr = static_cast<wchar_t *>(::GlobalLock(hand));
UCS2FromUTF8(drag.s, drag.len, uptr, uchars);
uptr[uchars] = 0;
}
} else {
hand = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, drag.len + 1);
if (hand) {
char *ptr = static_cast<char *>(::GlobalLock(hand));
for (int i = 0; i < drag.len; i++) {
ptr[i] = drag.s[i];
}
ptr[drag.len] = '\0';
}
}
::GlobalUnlock(hand);
pSTM->hGlobal = hand;
pSTM->pUnkForRelease = 0;
return S_OK;
}
bool ScintillaWin::Register(HINSTANCE hInstance_) {
hInstance = hInstance_;
bool result;
#if 0
// Register the Scintilla class
if (IsNT()) {
//if (0) {
// Register Scintilla as a wide character window
WNDCLASSEXW wndclass;
wndclass.cbSize = sizeof(wndclass);
wndclass.style = CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = ::ScintillaWin::SWndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = sizeof(ScintillaWin *);
wndclass.hInstance = hInstance;
wndclass.hIcon = NULL;
wndclass.hCursor = NULL;
wndclass.hbrBackground = NULL;
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = L"Scintilla";
wndclass.hIconSm = 0;
result = ::RegisterClassExW(&wndclass);
} else {
#endif
// Register Scintilla as a normal character window
WNDCLASSEX wndclass;
wndclass.cbSize = sizeof(wndclass);
wndclass.style = CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = ::ScintillaWin::SWndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = sizeof(ScintillaWin *);
wndclass.hInstance = hInstance;
wndclass.hIcon = NULL;
wndclass.hCursor = NULL;
wndclass.hbrBackground = NULL;
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = scintillaClassName;
wndclass.hIconSm = 0;
result = ::RegisterClassEx(&wndclass) != 0;
//}
if (result) {
// Register the CallTip class
WNDCLASSEX wndclassc;
wndclassc.cbSize = sizeof(wndclassc);
wndclassc.style = CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW;
wndclassc.cbClsExtra = 0;
wndclassc.cbWndExtra = sizeof(ScintillaWin *);
wndclassc.hInstance = hInstance;
wndclassc.hIcon = NULL;
wndclassc.hbrBackground = NULL;
wndclassc.lpszMenuName = NULL;
wndclassc.lpfnWndProc = ScintillaWin::CTWndProc;
wndclassc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
wndclassc.lpszClassName = callClassName;
wndclassc.hIconSm = 0;
result = ::RegisterClassEx(&wndclassc) != 0;
}
return result;
}
bool ScintillaWin::Unregister() {
bool result = ::UnregisterClass(scintillaClassName, hInstance) != 0;
if (::UnregisterClass(callClassName, hInstance) == 0)
result = false;
return result;
}
// Take care of 32/64 bit pointers
#ifdef GetWindowLongPtr
static void *PointerFromWindow(HWND hWnd) {
return reinterpret_cast<void *>(::GetWindowLongPtr(hWnd, 0));
}
static void SetWindowPointer(HWND hWnd, void *ptr) {
::SetWindowLongPtr(hWnd, 0, reinterpret_cast<LONG_PTR>(ptr));
}
#else
static void *PointerFromWindow(HWND hWnd) {
return reinterpret_cast<void *>(::GetWindowLong(hWnd, 0));
}
static void SetWindowPointer(HWND hWnd, void *ptr) {
::SetWindowLong(hWnd, 0, reinterpret_cast<LONG>(ptr));
}
#endif
sptr_t PASCAL ScintillaWin::CTWndProc(
HWND hWnd, UINT iMessage, WPARAM wParam, sptr_t lParam) {
// Find C++ object associated with window.
ScintillaWin *sciThis = reinterpret_cast<ScintillaWin *>(PointerFromWindow(hWnd));
// ctp will be zero if WM_CREATE not seen yet
if (sciThis == 0) {
if (iMessage == WM_CREATE) {
// Associate CallTip object with window
CREATESTRUCT *pCreate = reinterpret_cast<CREATESTRUCT *>(lParam);
SetWindowPointer(hWnd, pCreate->lpCreateParams);
return 0;
} else {
return ::DefWindowProc(hWnd, iMessage, wParam, lParam);
}
} else {
if (iMessage == WM_DESTROY) {
::SetWindowLong(hWnd, 0, 0);
return ::DefWindowProc(hWnd, iMessage, wParam, lParam);
} else if (iMessage == WM_PAINT) {
PAINTSTRUCT ps;
::BeginPaint(hWnd, &ps);
Surface *surfaceWindow = Surface::Allocate();
if (surfaceWindow) {
surfaceWindow->Init(ps.hdc, hWnd);
surfaceWindow->SetUnicodeMode(SC_CP_UTF8 == sciThis->ct.codePage);
surfaceWindow->SetDBCSMode(sciThis->ct.codePage);
sciThis->ct.PaintCT(surfaceWindow);
surfaceWindow->Release();
delete surfaceWindow;
}
::EndPaint(hWnd, &ps);
return 0;
} else if ((iMessage == WM_NCLBUTTONDOWN) || (iMessage == WM_NCLBUTTONDBLCLK)) {
POINT pt;
pt.x = static_cast<short>(LOWORD(lParam));
pt.y = static_cast<short>(HIWORD(lParam));
ScreenToClient(hWnd, &pt);
sciThis->ct.MouseClick(Point(pt.x, pt.y));
sciThis->CallTipClick();
return 0;
} else if (iMessage == WM_LBUTTONDOWN) {
// This does not fire due to the hit test code
sciThis->ct.MouseClick(Point::FromLong(lParam));
sciThis->CallTipClick();
return 0;
} else if (iMessage == WM_SETCURSOR) {
::SetCursor(::LoadCursor(NULL,IDC_ARROW));
return 0;
} else if (iMessage == WM_NCHITTEST) {
return HTCAPTION;
} else {
return ::DefWindowProc(hWnd, iMessage, wParam, lParam);
}
}
}
sptr_t ScintillaWin::DirectFunction(
ScintillaWin *sci, UINT iMessage, uptr_t wParam, sptr_t lParam) {
return sci->WndProc(iMessage, wParam, lParam);
}
extern "C" __declspec(dllexport) sptr_t __stdcall Scintilla_DirectFunction(
ScintillaWin *sci, UINT iMessage, uptr_t wParam, sptr_t lParam) {
return sci->WndProc(iMessage, wParam, lParam);
}
sptr_t PASCAL ScintillaWin::SWndProc(
HWND hWnd, UINT iMessage, WPARAM wParam, sptr_t lParam) {
//Platform::DebugPrintf("S W:%x M:%x WP:%x L:%x\n", hWnd, iMessage, wParam, lParam);
// Find C++ object associated with window.
ScintillaWin *sci = reinterpret_cast<ScintillaWin *>(PointerFromWindow(hWnd));
// sci will be zero if WM_CREATE not seen yet
if (sci == 0) {
if (iMessage == WM_CREATE) {
// Create C++ object associated with window
sci = new ScintillaWin(hWnd);
SetWindowPointer(hWnd, sci);
return sci->WndProc(iMessage, wParam, lParam);
} else {
return ::DefWindowProc(hWnd, iMessage, wParam, lParam);
}
} else {
if (iMessage == WM_DESTROY) {
sci->Finalise();
delete sci;
::SetWindowLong(hWnd, 0, 0);
return ::DefWindowProc(hWnd, iMessage, wParam, lParam);
} else {
return sci->WndProc(iMessage, wParam, lParam);
}
}
}
// This function is externally visible so it can be called from container when building statically.
// Must be called once only.
bool Scintilla_RegisterClasses(void *hInstance) {
Platform_Initialise(hInstance);
bool result = ScintillaWin::Register(reinterpret_cast<HINSTANCE>(hInstance));
#ifdef SCI_LEXER
Scintilla_LinkLexers();
#endif
return result;
}
// This function is externally visible so it can be called from container when building statically.
bool Scintilla_ReleaseResources() {
bool result = ScintillaWin::Unregister();
Platform_Finalise();
return result;
}
#ifndef STATIC_BUILD
extern "C" int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID) {
//Platform::DebugPrintf("Scintilla::DllMain %d %d\n", hInstance, dwReason);
if (dwReason == DLL_PROCESS_ATTACH) {
if (!Scintilla_RegisterClasses(hInstance))
return FALSE;
} else if (dwReason == DLL_PROCESS_DETACH) {
Scintilla_ReleaseResources();
}
return TRUE;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -