https://git.reactos.org/?p=reactos.git;a=commitdiff;h=ebe3d5273e47f382f4465…
commit ebe3d5273e47f382f44657ebf29c7632b23bbe5e
Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Sun May 13 22:15:41 2018 +0200
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Sun May 13 22:25:55 2018 +0200
[CLIPBRD] Improvements for the Clipboard Viewer.
- Improve the scrolling support for bitmaps, DIBs and text formats.
This completes the work started in CORE-10679 by Ricardo Hanke.
Includes scrolling with the keyboard and the mouse wheel.
- Add support for the CF_DSP* clipboard formats, as well as CF_TEXT
and CF_OEMTEXT.
- Add support for owner-display clipboard format CF_OWNERDISPLAY.
- Realize any palette found in the clipboard (CF_PALETTE) before
displaying the clipboard data format we want.
- Remove dead code.
- Update the file headers.
---
base/applications/clipbrd/clipbrd.c | 332 +++++++++++++++++++---------
base/applications/clipbrd/clipbrd.rc | 13 +-
base/applications/clipbrd/cliputils.c | 254 ++++++++++++++++++++--
base/applications/clipbrd/cliputils.h | 31 ++-
base/applications/clipbrd/fileutils.c | 17 +-
base/applications/clipbrd/fileutils.h | 15 +-
base/applications/clipbrd/precomp.h | 19 +-
base/applications/clipbrd/resources.h | 7 +
base/applications/clipbrd/scrollutils.c | 371 +++++++++++++++-----------------
base/applications/clipbrd/scrollutils.h | 39 ++--
base/applications/clipbrd/winutils.c | 222 ++++++++++++-------
base/applications/clipbrd/winutils.h | 22 +-
12 files changed, 898 insertions(+), 444 deletions(-)
diff --git a/base/applications/clipbrd/clipbrd.c b/base/applications/clipbrd/clipbrd.c
index f46daeb6e4..280cc6f78e 100644
--- a/base/applications/clipbrd/clipbrd.c
+++ b/base/applications/clipbrd/clipbrd.c
@@ -1,9 +1,9 @@
/*
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS Clipboard Viewer
- * FILE: base/applications/clipbrd/clipbrd.c
- * PURPOSE: Provides a view of the contents of the ReactOS clipboard.
- * PROGRAMMERS: Ricardo Hanke
+ * PROJECT: ReactOS Clipboard Viewer
+ * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE: Provides a view of the contents of the ReactOS clipboard.
+ * COPYRIGHT: Copyright 2015-2018 Ricardo Hanke
+ * Copyright 2015-2018 Hermes Belusca-Maito
*/
#include "precomp.h"
@@ -13,26 +13,12 @@ static const WCHAR szClassName[] = L"ClipBookWClass";
CLIPBOARD_GLOBALS Globals;
SCROLLSTATE Scrollstate;
-static void UpdateLinesToScroll(void)
-{
- UINT uLinesToScroll;
-
- if (!SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &uLinesToScroll, 0))
- {
- Globals.uLinesToScroll = 3;
- }
- else
- {
- Globals.uLinesToScroll = uLinesToScroll;
- }
-}
-
static void SaveClipboardToFile(void)
{
OPENFILENAMEW sfn;
+ LPWSTR c;
WCHAR szFileName[MAX_PATH];
WCHAR szFilterMask[MAX_STRING_LEN + 10];
- LPWSTR c;
ZeroMemory(&szFilterMask, sizeof(szFilterMask));
c = szFilterMask + LoadStringW(Globals.hInstance, STRING_FORMAT_NT, szFilterMask,
MAX_STRING_LEN) + 1;
@@ -87,9 +73,9 @@ static void LoadClipboardDataFromFile(LPWSTR lpszFileName)
static void LoadClipboardFromFile(void)
{
OPENFILENAMEW ofn;
+ LPWSTR c;
WCHAR szFileName[MAX_PATH];
WCHAR szFilterMask[MAX_STRING_LEN + 10];
- LPWSTR c;
ZeroMemory(&szFilterMask, sizeof(szFilterMask));
c = szFilterMask + LoadStringW(Globals.hInstance, STRING_FORMAT_GEN, szFilterMask,
MAX_STRING_LEN) + 1;
@@ -123,6 +109,8 @@ static void LoadClipboardFromDrop(HDROP hDrop)
static void SetDisplayFormat(UINT uFormat)
{
+ RECT rc;
+
CheckMenuItem(Globals.hMenu, Globals.uCheckedItem, MF_BYCOMMAND | MF_UNCHECKED);
Globals.uCheckedItem = uFormat + CMD_AUTOMATIC;
CheckMenuItem(Globals.hMenu, Globals.uCheckedItem, MF_BYCOMMAND | MF_CHECKED);
@@ -136,13 +124,10 @@ static void SetDisplayFormat(UINT uFormat)
Globals.uDisplayFormat = uFormat;
}
- if (Globals.hDspBmp)
- {
- DeleteObject(Globals.hDspBmp);
- }
-
- ZeroMemory(&Scrollstate, sizeof(Scrollstate));
- UpdateWindowScrollState(Globals.hMainWnd, Globals.hDspBmp, &Scrollstate);
+ GetClipboardDataDimensions(Globals.uDisplayFormat, &rc);
+ Scrollstate.CurrentX = Scrollstate.CurrentY = 0;
+ Scrollstate.iWheelCarryoverX = Scrollstate.iWheelCarryoverY = 0;
+ UpdateWindowScrollState(Globals.hMainWnd, rc.right, rc.bottom, &Scrollstate);
InvalidateRect(Globals.hMainWnd, NULL, TRUE);
}
@@ -169,8 +154,8 @@ static void InitMenuPopup(HMENU hMenu, LPARAM index)
static void UpdateDisplayMenu(void)
{
UINT uFormat;
- WCHAR szFormatName[MAX_FMT_NAME_LEN + 1];
HMENU hMenu;
+ WCHAR szFormatName[MAX_FMT_NAME_LEN + 1];
hMenu = GetSubMenu(Globals.hMenu, DISPLAY_MENU_POS);
@@ -187,27 +172,34 @@ static void UpdateDisplayMenu(void)
AppendMenuW(hMenu, MF_SEPARATOR, 0, NULL);
- uFormat = EnumClipboardFormats(0);
- while (uFormat)
+ /* Display the supported clipboard formats first */
+ for (uFormat = EnumClipboardFormats(0); uFormat;
+ uFormat = EnumClipboardFormats(uFormat))
{
- RetrieveClipboardFormatName(Globals.hInstance, uFormat, TRUE, szFormatName,
ARRAYSIZE(szFormatName));
+ if (IsClipboardFormatSupported(uFormat))
+ {
+ RetrieveClipboardFormatName(Globals.hInstance, uFormat, TRUE,
+ szFormatName, ARRAYSIZE(szFormatName));
+ AppendMenuW(hMenu, MF_STRING, CMD_AUTOMATIC + uFormat, szFormatName);
+ }
+ }
+ /* Now display the unsupported clipboard formats */
+ for (uFormat = EnumClipboardFormats(0); uFormat;
+ uFormat = EnumClipboardFormats(uFormat))
+ {
if (!IsClipboardFormatSupported(uFormat))
{
+ RetrieveClipboardFormatName(Globals.hInstance, uFormat, TRUE,
+ szFormatName, ARRAYSIZE(szFormatName));
AppendMenuW(hMenu, MF_STRING | MF_GRAYED, 0, szFormatName);
}
- else
- {
- AppendMenuW(hMenu, MF_STRING, CMD_AUTOMATIC + uFormat, szFormatName);
- }
-
- uFormat = EnumClipboardFormats(uFormat);
}
CloseClipboard();
}
-static int ClipboardCommandHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+static int OnCommand(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (LOWORD(wParam))
{
@@ -274,68 +266,113 @@ static int ClipboardCommandHandler(HWND hWnd, UINT uMsg, WPARAM
wParam, LPARAM l
return 0;
}
-static void ClipboardPaintHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+static void OnPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
+ COLORREF crOldBkColor, crOldTextColor;
RECT rc;
if (!OpenClipboard(Globals.hMainWnd))
return;
hdc = BeginPaint(hWnd, &ps);
- GetClientRect(hWnd, &rc);
+
+ /* Erase the background if needed */
+ if (ps.fErase)
+ FillRect(ps.hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
+
+ /* Set the correct background and text colors */
+ crOldBkColor = SetBkColor(ps.hdc, GetSysColor(COLOR_WINDOW));
+ crOldTextColor = SetTextColor(ps.hdc, GetSysColor(COLOR_WINDOWTEXT));
+
+ /* Realize the clipboard palette if there is one */
+ RealizeClipboardPalette(ps.hdc);
switch (Globals.uDisplayFormat)
{
case CF_NONE:
{
+ /* The clipboard is empty */
break;
}
+ case CF_DSPTEXT:
+ case CF_TEXT:
+ case CF_OEMTEXT:
case CF_UNICODETEXT:
{
- DrawTextFromClipboard(hdc, &rc, DT_LEFT | DT_NOPREFIX);
+ DrawTextFromClipboard(Globals.uDisplayFormat, ps, Scrollstate);
break;
}
+ case CF_DSPBITMAP:
case CF_BITMAP:
{
- BitBltFromClipboard(hdc, rc.left, rc.top, rc.right, rc.bottom, 0, 0,
SRCCOPY);
+ BitBltFromClipboard(ps, Scrollstate, SRCCOPY);
break;
}
case CF_DIB:
- {
- SetDIBitsToDeviceFromClipboard(CF_DIB, hdc, rc.left, rc.top, 0, 0, 0,
DIB_RGB_COLORS);
- break;
- }
-
case CF_DIBV5:
{
- SetDIBitsToDeviceFromClipboard(CF_DIBV5, hdc, rc.left, rc.top, 0, 0, 0,
DIB_RGB_COLORS);
+ SetDIBitsToDeviceFromClipboard(Globals.uDisplayFormat, ps, Scrollstate,
DIB_RGB_COLORS);
break;
}
+ case CF_DSPMETAFILEPICT:
case CF_METAFILEPICT:
{
+ GetClientRect(hWnd, &rc);
PlayMetaFileFromClipboard(hdc, &rc);
break;
}
+ case CF_DSPENHMETAFILE:
case CF_ENHMETAFILE:
{
+ GetClientRect(hWnd, &rc);
PlayEnhMetaFileFromClipboard(hdc, &rc);
break;
}
+ // case CF_PALETTE:
+ // TODO: Draw a palette with squares filled with colors.
+ // break;
+
+ case CF_OWNERDISPLAY:
+ {
+ HGLOBAL hglb;
+ PPAINTSTRUCT pps;
+
+ hglb = GlobalAlloc(GMEM_MOVEABLE, sizeof(ps));
+ if (hglb)
+ {
+ pps = GlobalLock(hglb);
+ CopyMemory(pps, &ps, sizeof(ps));
+ GlobalUnlock(hglb);
+
+ SendClipboardOwnerMessage(TRUE, WM_PAINTCLIPBOARD,
+ (WPARAM)hWnd, (LPARAM)hglb);
+
+ GlobalFree(hglb);
+ }
+ break;
+ }
+
default:
{
- DrawTextFromResource(Globals.hInstance, ERROR_UNSUPPORTED_FORMAT, hdc,
&rc, DT_CENTER | DT_WORDBREAK | DT_NOPREFIX);
+ GetClientRect(hWnd, &rc);
+ DrawTextFromResource(Globals.hInstance, ERROR_UNSUPPORTED_FORMAT,
+ hdc, &rc, DT_CENTER | DT_WORDBREAK | DT_NOPREFIX);
break;
}
}
+ /* Restore the original colors */
+ SetTextColor(ps.hdc, crOldTextColor);
+ SetBkColor(ps.hdc, crOldBkColor);
+
EndPaint(hWnd, &ps);
CloseClipboard();
@@ -347,12 +384,29 @@ static LRESULT WINAPI MainWndProc(HWND hWnd, UINT uMsg, WPARAM
wParam, LPARAM lP
{
case WM_CREATE:
{
+ TEXTMETRICW tm;
+ HDC hDC = GetDC(hWnd);
+
+ /*
+ * Note that the method with GetObjectW just returns
+ * the original parameters with which the font was created.
+ */
+ if (GetTextMetricsW(hDC, &tm))
+ {
+ Globals.CharWidth = tm.tmMaxCharWidth; // tm.tmAveCharWidth;
+ Globals.CharHeight = tm.tmHeight + tm.tmExternalLeading;
+ }
+ ReleaseDC(hWnd, hDC);
+
+
Globals.hMenu = GetMenu(hWnd);
Globals.hWndNext = SetClipboardViewer(hWnd);
-
+
// For now, the Help dialog item is disabled because of lacking of HTML
support
EnableMenuItem(Globals.hMenu, CMD_HELP, MF_BYCOMMAND | MF_GRAYED);
-
+
+ UpdateLinesToScroll(&Scrollstate);
+
UpdateDisplayMenu();
SetDisplayFormat(0);
break;
@@ -367,61 +421,114 @@ static LRESULT WINAPI MainWndProc(HWND hWnd, UINT uMsg, WPARAM
wParam, LPARAM lP
case WM_DESTROY:
{
ChangeClipboardChain(hWnd, Globals.hWndNext);
+
+ if (Globals.uDisplayFormat == CF_OWNERDISPLAY)
+ {
+ HGLOBAL hglb;
+ PRECT prc;
+
+ hglb = GlobalAlloc(GMEM_MOVEABLE, sizeof(*prc));
+ if (hglb)
+ {
+ prc = GlobalLock(hglb);
+ SetRectEmpty(prc);
+ GlobalUnlock(hglb);
+
+ SendClipboardOwnerMessage(TRUE, WM_SIZECLIPBOARD,
+ (WPARAM)hWnd, (LPARAM)hglb);
+
+ GlobalFree(hglb);
+ }
+ }
+
PostQuitMessage(0);
break;
}
case WM_PAINT:
{
- ClipboardPaintHandler(hWnd, uMsg, wParam, lParam);
+ OnPaint(hWnd, wParam, lParam);
break;
}
case WM_KEYDOWN:
{
- HandleKeyboardScrollEvents(hWnd, uMsg, wParam, lParam);
+ OnKeyScroll(hWnd, wParam, lParam, &Scrollstate);
break;
}
case WM_MOUSEWHEEL:
+ case WM_MOUSEHWHEEL:
{
- HandleMouseScrollEvents(hWnd, uMsg, wParam, lParam, &Scrollstate);
+ OnMouseScroll(hWnd, uMsg, wParam, lParam, &Scrollstate);
break;
}
case WM_HSCROLL:
{
- HandleHorizontalScrollEvents(hWnd, uMsg, wParam, lParam, &Scrollstate);
+ // NOTE: Windows uses an offset of 16 pixels
+ OnScroll(hWnd, SB_HORZ, wParam, 5, &Scrollstate);
break;
}
case WM_VSCROLL:
{
- HandleVerticalScrollEvents(hWnd, uMsg, wParam, lParam, &Scrollstate);
+ // NOTE: Windows uses an offset of 16 pixels
+ OnScroll(hWnd, SB_VERT, wParam, 5, &Scrollstate);
break;
}
case WM_SIZE:
{
- UpdateWindowScrollState(hWnd, Globals.hDspBmp, &Scrollstate);
+ RECT rc;
- if ((Globals.uDisplayFormat == CF_METAFILEPICT) ||
- (Globals.uDisplayFormat == CF_ENHMETAFILE) ||
- (Globals.uDisplayFormat == CF_DSPENHMETAFILE) ||
- (Globals.uDisplayFormat == CF_DSPMETAFILEPICT))
+ if (Globals.uDisplayFormat == CF_OWNERDISPLAY)
{
- InvalidateRect(Globals.hMainWnd, NULL, FALSE);
+ HGLOBAL hglb;
+ PRECT prc;
+
+ hglb = GlobalAlloc(GMEM_MOVEABLE, sizeof(*prc));
+ if (hglb)
+ {
+ prc = GlobalLock(hglb);
+ if (wParam == SIZE_MINIMIZED)
+ SetRectEmpty(prc);
+ else
+ GetClientRect(hWnd, prc);
+ GlobalUnlock(hglb);
+
+ SendClipboardOwnerMessage(TRUE, WM_SIZECLIPBOARD,
+ (WPARAM)hWnd, (LPARAM)hglb);
+
+ GlobalFree(hglb);
+ }
+ break;
}
- else if (!IsClipboardFormatSupported(Globals.uDisplayFormat))
+
+ GetClipboardDataDimensions(Globals.uDisplayFormat, &rc);
+ UpdateWindowScrollState(hWnd, rc.right, rc.bottom, &Scrollstate);
+
+ // NOTE: There still are little problems drawing
+ // the background when displaying clipboard text.
+ if (!IsClipboardFormatSupported(Globals.uDisplayFormat) ||
+ Globals.uDisplayFormat == CF_DSPTEXT ||
+ Globals.uDisplayFormat == CF_TEXT ||
+ Globals.uDisplayFormat == CF_OEMTEXT ||
+ Globals.uDisplayFormat == CF_UNICODETEXT)
{
InvalidateRect(Globals.hMainWnd, NULL, TRUE);
}
+ else
+ {
+ InvalidateRect(Globals.hMainWnd, NULL, FALSE);
+ }
break;
}
case WM_CHANGECBCHAIN:
{
+ /* Transmit through the clipboard viewer chain */
if ((HWND)wParam == Globals.hWndNext)
{
Globals.hWndNext = (HWND)lParam;
@@ -434,11 +541,32 @@ static LRESULT WINAPI MainWndProc(HWND hWnd, UINT uMsg, WPARAM
wParam, LPARAM lP
break;
}
+ case WM_DESTROYCLIPBOARD:
+ break;
+
+ case WM_RENDERALLFORMATS:
+ {
+ /*
+ * When the user has cleared the clipboard via the DELETE command,
+ * we (clipboard viewer) become the clipboard owner. When we are
+ * subsequently closed, this message is then sent to us so that
+ * we get a chance to render everything we can. Since we don't have
+ * anything to render, just empty the clipboard.
+ */
+ DeleteClipboardContent();
+ break;
+ }
+
+ case WM_RENDERFORMAT:
+ // TODO!
+ break;
+
case WM_DRAWCLIPBOARD:
{
UpdateDisplayMenu();
SetDisplayFormat(0);
+ /* Pass the message to the next window in clipboard viewer chain */
SendMessageW(Globals.hWndNext, uMsg, wParam, lParam);
break;
}
@@ -451,7 +579,7 @@ static LRESULT WINAPI MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam,
LPARAM lP
}
else
{
- ClipboardCommandHandler(hWnd, uMsg, wParam, lParam);
+ OnCommand(hWnd, uMsg, wParam, lParam);
}
break;
}
@@ -468,9 +596,36 @@ static LRESULT WINAPI MainWndProc(HWND hWnd, UINT uMsg, WPARAM
wParam, LPARAM lP
break;
}
+ case WM_PALETTECHANGED:
+ {
+ /* Ignore if this comes from ourselves */
+ if ((HWND)wParam == hWnd)
+ break;
+
+ /* Fall back to WM_QUERYNEWPALETTE */
+ }
+
case WM_QUERYNEWPALETTE:
{
- if (RealizeClipboardPalette(hWnd) != GDI_ERROR)
+ BOOL Success;
+ HDC hDC;
+
+ if (!OpenClipboard(Globals.hMainWnd))
+ return FALSE;
+
+ hDC = GetDC(hWnd);
+ if (!hDC)
+ {
+ CloseClipboard();
+ return FALSE;
+ }
+
+ Success = RealizeClipboardPalette(hDC);
+
+ ReleaseDC(hWnd, hDC);
+ CloseClipboard();
+
+ if (Success)
{
InvalidateRect(hWnd, NULL, TRUE);
UpdateWindow(hWnd);
@@ -479,19 +634,6 @@ static LRESULT WINAPI MainWndProc(HWND hWnd, UINT uMsg, WPARAM
wParam, LPARAM lP
return FALSE;
}
- case WM_PALETTECHANGED:
- {
- if ((HWND)wParam != hWnd)
- {
- if (RealizeClipboardPalette(hWnd) != GDI_ERROR)
- {
- InvalidateRect(hWnd, NULL, TRUE);
- UpdateWindow(hWnd);
- }
- }
- break;
- }
-
case WM_SYSCOLORCHANGE:
{
SetDisplayFormat(Globals.uDisplayFormat);
@@ -502,7 +644,7 @@ static LRESULT WINAPI MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam,
LPARAM lP
{
if (wParam == SPI_SETWHEELSCROLLLINES)
{
- UpdateLinesToScroll();
+ UpdateLinesToScroll(&Scrollstate);
}
break;
}
@@ -512,6 +654,7 @@ static LRESULT WINAPI MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam,
LPARAM lP
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
}
+
return 0;
}
@@ -530,6 +673,16 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPWSTR lpCmdLi
return 0;
}
+ switch (GetUserDefaultUILanguage())
+ {
+ case MAKELANGID(LANG_HEBREW, SUBLANG_DEFAULT):
+ SetProcessDefaultLayout(LAYOUT_RTL);
+ break;
+
+ default:
+ break;
+ }
+
ZeroMemory(&Globals, sizeof(Globals));
Globals.hInstance = hInstance;
@@ -542,16 +695,6 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPWSTR lpCmdLi
wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wndclass.lpszMenuName = MAKEINTRESOURCEW(MAIN_MENU);
wndclass.lpszClassName = szClassName;
-
- switch (GetUserDefaultUILanguage())
- {
- case MAKELANGID(LANG_HEBREW, SUBLANG_DEFAULT):
- SetProcessDefaultLayout(LAYOUT_RTL);
- break;
-
- default:
- break;
- }
if (!RegisterClassExW(&wndclass))
{
@@ -559,6 +702,8 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPWSTR lpCmdLi
return 0;
}
+ ZeroMemory(&Scrollstate, sizeof(Scrollstate));
+
LoadStringW(hInstance, STRING_CLIPBOARD, szBuffer, ARRAYSIZE(szBuffer));
Globals.hMainWnd = CreateWindowExW(WS_EX_CLIENTEDGE | WS_EX_ACCEPTFILES,
szClassName,
@@ -591,8 +736,6 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPWSTR lpCmdLi
if (lpCmdLine != NULL && *lpCmdLine)
LoadClipboardDataFromFile(lpCmdLine);
- UpdateLinesToScroll();
-
while (GetMessageW(&msg, 0, 0, 0))
{
if (!TranslateAcceleratorW(Globals.hMainWnd, hAccel, &msg))
@@ -602,10 +745,5 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPWSTR lpCmdLi
}
}
- if (Globals.hDspBmp)
- {
- DeleteObject(Globals.hDspBmp);
- }
-
return (int)msg.wParam;
}
diff --git a/base/applications/clipbrd/clipbrd.rc b/base/applications/clipbrd/clipbrd.rc
index 5f3e293bc4..178c6ce697 100644
--- a/base/applications/clipbrd/clipbrd.rc
+++ b/base/applications/clipbrd/clipbrd.rc
@@ -1,11 +1,18 @@
+/*
+ * PROJECT: ReactOS Clipboard Viewer
+ * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE: Resources file.
+ * COPYRIGHT: Copyright 2015-2018 Ricardo Hanke
+ */
+
#include <windef.h>
#include <winuser.h>
#include "resources.h"
-#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Clipboard Viewer"
-#define REACTOS_STR_INTERNAL_NAME "clipbrd"
-#define REACTOS_STR_ORIGINAL_FILENAME "clipbrd.exe"
+#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Clipboard Viewer"
+#define REACTOS_STR_INTERNAL_NAME "clipbrd"
+#define REACTOS_STR_ORIGINAL_FILENAME "clipbrd.exe"
#include <reactos/version.rc>
CLIPBRD_ICON ICON "res/clipbrd.ico"
diff --git a/base/applications/clipbrd/cliputils.c
b/base/applications/clipbrd/cliputils.c
index e13348a9eb..daee8439a8 100644
--- a/base/applications/clipbrd/cliputils.c
+++ b/base/applications/clipbrd/cliputils.c
@@ -1,13 +1,32 @@
/*
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS Clipboard Viewer
- * FILE: base/applications/clipbrd/cliputils.c
- * PURPOSE: Clipboard helper functions.
- * PROGRAMMERS: Ricardo Hanke
+ * PROJECT: ReactOS Clipboard Viewer
+ * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE: Clipboard helper functions.
+ * COPYRIGHT: Copyright 2015-2018 Ricardo Hanke
+ * Copyright 2015-2018 Hermes Belusca-Maito
*/
#include "precomp.h"
+LRESULT
+SendClipboardOwnerMessage(
+ IN BOOL bUnicode,
+ IN UINT uMsg,
+ IN WPARAM wParam,
+ IN LPARAM lParam)
+{
+ HWND hwndOwner;
+
+ hwndOwner = GetClipboardOwner();
+ if (!hwndOwner)
+ return GetLastError();
+
+ if (bUnicode)
+ return SendMessageW(hwndOwner, uMsg, wParam, lParam);
+ else
+ return SendMessageA(hwndOwner, uMsg, wParam, lParam);
+}
+
static int
GetPredefinedClipboardFormatName(HINSTANCE hInstance,
UINT uFormat,
@@ -79,18 +98,36 @@ RetrieveClipboardFormatName(HINSTANCE hInstance,
PVOID lpszFormat,
UINT cch)
{
- if (!GetPredefinedClipboardFormatName(hInstance, uFormat, Unicode, lpszFormat, cch))
+ ZeroMemory(lpszFormat, cch * (Unicode ? sizeof(WCHAR) : sizeof(CHAR)));
+
+ /* Check for predefined clipboard format */
+ if (GetPredefinedClipboardFormatName(hInstance, uFormat, Unicode, lpszFormat, cch) !=
0)
+ return;
+
+ /* Check for owner-display format */
+ if (uFormat == CF_OWNERDISPLAY)
{
- if (Unicode)
+ if (SendClipboardOwnerMessage(Unicode, WM_ASKCBFORMATNAME,
+ (WPARAM)cch, (LPARAM)lpszFormat) != 0)
{
- if (!GetClipboardFormatNameW(uFormat, (LPWSTR)lpszFormat, cch))
+ if (Unicode)
LoadStringW(hInstance, STRING_CF_UNKNOWN, (LPWSTR)lpszFormat, cch);
- }
- else
- {
- if (!GetClipboardFormatNameA(uFormat, (LPSTR)lpszFormat, cch))
+ else
LoadStringA(hInstance, STRING_CF_UNKNOWN, (LPSTR)lpszFormat, cch);
}
+ return;
+ }
+
+ /* Fallback to registered clipboard format */
+ if (Unicode)
+ {
+ if (!GetClipboardFormatNameW(uFormat, (LPWSTR)lpszFormat, cch))
+ LoadStringW(hInstance, STRING_CF_UNKNOWN, (LPWSTR)lpszFormat, cch);
+ }
+ else
+ {
+ if (!GetClipboardFormatNameA(uFormat, (LPSTR)lpszFormat, cch))
+ LoadStringA(hInstance, STRING_CF_UNKNOWN, (LPSTR)lpszFormat, cch);
}
}
@@ -112,13 +149,22 @@ void DeleteClipboardContent(void)
UINT GetAutomaticClipboardFormat(void)
{
- static UINT uFormatList[] = {
+ static UINT uFormatList[] =
+ {
+ CF_OWNERDISPLAY,
CF_UNICODETEXT,
+ CF_TEXT,
+ CF_OEMTEXT,
CF_ENHMETAFILE,
CF_METAFILEPICT,
CF_DIBV5,
CF_DIB,
- CF_BITMAP
+ CF_BITMAP,
+ CF_DSPTEXT,
+ CF_DSPBITMAP,
+ CF_DSPMETAFILEPICT,
+ CF_DSPENHMETAFILE,
+ CF_PALETTE
};
return GetPriorityClipboardFormat(uFormatList, ARRAYSIZE(uFormatList));
@@ -128,12 +174,16 @@ BOOL IsClipboardFormatSupported(UINT uFormat)
{
switch (uFormat)
{
+ case CF_OWNERDISPLAY:
case CF_UNICODETEXT:
+ case CF_TEXT:
+ case CF_OEMTEXT:
case CF_BITMAP:
case CF_ENHMETAFILE:
case CF_METAFILEPICT:
case CF_DIB:
case CF_DIBV5:
+ case CF_HDROP:
{
return TRUE;
}
@@ -144,3 +194,179 @@ BOOL IsClipboardFormatSupported(UINT uFormat)
}
}
}
+
+SIZE_T
+GetLineExtentW(
+ IN LPCWSTR lpText,
+ OUT LPCWSTR* lpNextLine)
+{
+ LPCWSTR ptr;
+
+ /* Find the next line of text (lpText is NULL-terminated) */
+ /* For newlines, focus only on '\n', not on '\r' */
+ ptr = wcschr(lpText, L'\n'); // Find the end of this line.
+ if (ptr)
+ {
+ /* We have the end of this line, go to the next line (ignore the endline in the
count) */
+ *lpNextLine = ptr + 1;
+ }
+ else
+ {
+ /* This line was the last one, go pointing to the terminating NULL */
+ ptr = lpText + wcslen(lpText);
+ *lpNextLine = ptr;
+ }
+
+ return (ptr - lpText);
+}
+
+SIZE_T
+GetLineExtentA(
+ IN LPCSTR lpText,
+ OUT LPCSTR* lpNextLine)
+{
+ LPCSTR ptr;
+
+ /* Find the next line of text (lpText is NULL-terminated) */
+ /* For newlines, focus only on '\n', not on '\r' */
+ ptr = strchr(lpText, '\n'); // Find the end of this line.
+ if (ptr)
+ {
+ /* We have the end of this line, go to the next line (ignore the endline in the
count) */
+ *lpNextLine = ptr + 1;
+ }
+ else
+ {
+ /* This line was the last one, go pointing to the terminating NULL */
+ ptr = lpText + strlen(lpText);
+ *lpNextLine = ptr;
+ }
+
+ return (ptr - lpText);
+}
+
+BOOL GetClipboardDataDimensions(UINT uFormat, PRECT pRc)
+{
+ SetRectEmpty(pRc);
+
+ if (!OpenClipboard(Globals.hMainWnd))
+ {
+ return FALSE;
+ }
+
+ switch (uFormat)
+ {
+ case CF_DSPBITMAP:
+ case CF_BITMAP:
+ {
+ HBITMAP hBitmap;
+ BITMAP bmp;
+
+ hBitmap = (HBITMAP)GetClipboardData(CF_BITMAP);
+ GetObjectW(hBitmap, sizeof(bmp), &bmp);
+ SetRect(pRc, 0, 0, bmp.bmWidth, bmp.bmHeight);
+ break;
+ }
+
+ case CF_DIB:
+ case CF_DIBV5:
+ {
+ HGLOBAL hGlobal;
+ LPBITMAPINFOHEADER lpInfoHeader;
+
+ hGlobal = GetClipboardData(uFormat);
+ if (!hGlobal)
+ break;
+
+ lpInfoHeader = GlobalLock(hGlobal);
+ if (!lpInfoHeader)
+ break;
+
+ if (lpInfoHeader->biSize == sizeof(BITMAPCOREHEADER))
+ {
+ LPBITMAPCOREHEADER lpCoreHeader = (LPBITMAPCOREHEADER)lpInfoHeader;
+ SetRect(pRc, 0, 0,
+ lpCoreHeader->bcWidth,
+ lpCoreHeader->bcHeight);
+ }
+ else if ((lpInfoHeader->biSize == sizeof(BITMAPINFOHEADER)) ||
+ (lpInfoHeader->biSize == sizeof(BITMAPV4HEADER)) ||
+ (lpInfoHeader->biSize == sizeof(BITMAPV5HEADER)))
+ {
+ SetRect(pRc, 0, 0,
+ lpInfoHeader->biWidth,
+ /* NOTE: biHeight < 0 for bottom-up DIBs, or > 0 for
top-down DIBs */
+ (lpInfoHeader->biHeight > 0) ? lpInfoHeader->biHeight
+ : -lpInfoHeader->biHeight);
+ }
+ else
+ {
+ /* Invalid format */
+ }
+
+ GlobalUnlock(hGlobal);
+ break;
+ }
+
+ case CF_DSPTEXT:
+ case CF_TEXT:
+ case CF_OEMTEXT:
+ case CF_UNICODETEXT:
+ {
+ HDC hDC;
+ HGLOBAL hGlobal;
+ PVOID lpText, ptr;
+ DWORD dwSize;
+ SIZE txtSize = {0, 0};
+ SIZE_T lineSize;
+
+ hGlobal = GetClipboardData(uFormat);
+ if (!hGlobal)
+ break;
+
+ lpText = GlobalLock(hGlobal);
+ if (!lpText)
+ break;
+
+ hDC = GetDC(Globals.hMainWnd);
+
+ /* Find the size of the rectangle enclosing the text */
+ for (;;)
+ {
+ if (uFormat == CF_UNICODETEXT)
+ {
+ if (*(LPCWSTR)lpText == UNICODE_NULL)
+ break;
+ lineSize = GetLineExtentW(lpText, (LPCWSTR*)&ptr);
+ dwSize = GetTabbedTextExtentW(hDC, lpText, lineSize, 0, NULL);
+ }
+ else
+ {
+ if (*(LPCSTR)lpText == ANSI_NULL)
+ break;
+ lineSize = GetLineExtentA(lpText, (LPCSTR*)&ptr);
+ dwSize = GetTabbedTextExtentA(hDC, lpText, lineSize, 0, NULL);
+ }
+ txtSize.cx = max(txtSize.cx, LOWORD(dwSize));
+ txtSize.cy += HIWORD(dwSize);
+ lpText = ptr;
+ }
+
+ ReleaseDC(Globals.hMainWnd, hDC);
+
+ GlobalUnlock(hGlobal);
+
+ SetRect(pRc, 0, 0, txtSize.cx, txtSize.cy);
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+
+ CloseClipboard();
+
+ return TRUE;
+}
diff --git a/base/applications/clipbrd/cliputils.h
b/base/applications/clipbrd/cliputils.h
index 28d64b8b3e..f126108649 100644
--- a/base/applications/clipbrd/cliputils.h
+++ b/base/applications/clipbrd/cliputils.h
@@ -1,11 +1,20 @@
/*
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS Clipboard Viewer
- * FILE: base/applications/clipbrd/cliputils.h
- * PURPOSE: Clipboard helper functions.
- * PROGRAMMERS: Ricardo Hanke
+ * PROJECT: ReactOS Clipboard Viewer
+ * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE: Clipboard helper functions.
+ * COPYRIGHT: Copyright 2015-2018 Ricardo Hanke
+ * Copyright 2015-2018 Hermes Belusca-Maito
*/
+#pragma once
+
+LRESULT
+SendClipboardOwnerMessage(
+ IN BOOL bUnicode,
+ IN UINT uMsg,
+ IN WPARAM wParam,
+ IN LPARAM lParam);
+
void
RetrieveClipboardFormatName(HINSTANCE hInstance,
UINT uFormat,
@@ -16,3 +25,15 @@ RetrieveClipboardFormatName(HINSTANCE hInstance,
void DeleteClipboardContent(void);
UINT GetAutomaticClipboardFormat(void);
BOOL IsClipboardFormatSupported(UINT uFormat);
+
+SIZE_T
+GetLineExtentW(
+ IN LPCWSTR lpText,
+ OUT LPCWSTR* lpNextLine);
+
+SIZE_T
+GetLineExtentA(
+ IN LPCSTR lpText,
+ OUT LPCSTR* lpNextLine);
+
+BOOL GetClipboardDataDimensions(UINT uFormat, PRECT pRc);
diff --git a/base/applications/clipbrd/fileutils.c
b/base/applications/clipbrd/fileutils.c
index 3be9acb275..d4b3ba72f0 100644
--- a/base/applications/clipbrd/fileutils.c
+++ b/base/applications/clipbrd/fileutils.c
@@ -1,10 +1,9 @@
/*
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS Clipboard Viewer
- * FILE: base/applications/clipbrd/fileutils.c
- * PURPOSE: Clipboard file format helper functions.
- * PROGRAMMERS: Ricardo Hanke
- * Hermes Belusca-Maito
+ * PROJECT: ReactOS Clipboard Viewer
+ * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE: Clipboard file format helper functions.
+ * COPYRIGHT: Copyright 2015-2018 Ricardo Hanke
+ * Copyright 2015-2018 Hermes Belusca-Maito
*/
#include "precomp.h"
@@ -399,22 +398,22 @@ void ReadClipboardFile(LPCWSTR lpFileName)
break;
}
- case CF_BITMAP:
case CF_DSPBITMAP:
+ case CF_BITMAP:
{
bResult = ClipboardReadBitmap(hFile, dwOffData, dwLenData);
break;
}
- case CF_METAFILEPICT:
case CF_DSPMETAFILEPICT:
+ case CF_METAFILEPICT:
{
bResult = ClipboardReadMetafile(hFile, dwOffData, dwLenData);
break;
}
- case CF_ENHMETAFILE:
case CF_DSPENHMETAFILE:
+ case CF_ENHMETAFILE:
{
bResult = ClipboardReadEnhMetafile(hFile, dwOffData, dwLenData);
break;
diff --git a/base/applications/clipbrd/fileutils.h
b/base/applications/clipbrd/fileutils.h
index e103d8ee84..b17c45066a 100644
--- a/base/applications/clipbrd/fileutils.h
+++ b/base/applications/clipbrd/fileutils.h
@@ -1,15 +1,18 @@
/*
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS Clipboard Viewer
- * FILE: base/applications/clipbrd/fileutils.h
- * PURPOSE: Clipboard file format helper functions.
- * PROGRAMMERS: Ricardo Hanke
- * Hermes Belusca-Maito
+ * PROJECT: ReactOS Clipboard Viewer
+ * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE: Clipboard file format helper functions.
+ * COPYRIGHT: Copyright 2015-2018 Ricardo Hanke
+ * Copyright 2015-2018 Hermes Belusca-Maito
*/
+#pragma once
+
+/* Clipboard file format signatures */
#define CLIP_FMT_31 0xC350
#define CLIP_FMT_NT 0xC351
#define CLIP_FMT_BK 0xC352
+
#define MAX_FMT_NAME_LEN 79
/*
diff --git a/base/applications/clipbrd/precomp.h b/base/applications/clipbrd/precomp.h
index 5159ec2e5d..7a04b962c4 100644
--- a/base/applications/clipbrd/precomp.h
+++ b/base/applications/clipbrd/precomp.h
@@ -1,8 +1,18 @@
+/*
+ * PROJECT: ReactOS Clipboard Viewer
+ * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE: Precompiled header.
+ * COPYRIGHT: Copyright 2015-2018 Ricardo Hanke
+ */
+
#ifndef _CLIPBRD_PCH_
#define _CLIPBRD_PCH_
// #pragma once
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x600
+
#include <limits.h>
#include <assert.h>
@@ -19,11 +29,12 @@
#include "resources.h"
#include "cliputils.h"
#include "fileutils.h"
-#include "winutils.h"
#include "scrollutils.h"
+#include "winutils.h"
#define MAX_STRING_LEN 255
#define DISPLAY_MENU_POS 2
+
#define CF_NONE 0
typedef struct _CLIPBOARD_GLOBALS
@@ -34,8 +45,10 @@ typedef struct _CLIPBOARD_GLOBALS
HMENU hMenu;
UINT uDisplayFormat;
UINT uCheckedItem;
- UINT uLinesToScroll;
- HBITMAP hDspBmp;
+
+ /* Metrics of the current font */
+ LONG CharWidth;
+ LONG CharHeight;
} CLIPBOARD_GLOBALS;
extern CLIPBOARD_GLOBALS Globals;
diff --git a/base/applications/clipbrd/resources.h
b/base/applications/clipbrd/resources.h
index ac958ef625..afc9ae8fd9 100644
--- a/base/applications/clipbrd/resources.h
+++ b/base/applications/clipbrd/resources.h
@@ -1,3 +1,10 @@
+/*
+ * PROJECT: ReactOS Clipboard Viewer
+ * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE: Resources header.
+ * COPYRIGHT: Copyright 2015-2018 Ricardo Hanke
+ */
+
#pragma once
#define CLIPBRD_ICON 100
diff --git a/base/applications/clipbrd/scrollutils.c
b/base/applications/clipbrd/scrollutils.c
index 424921f321..87c6ce8334 100644
--- a/base/applications/clipbrd/scrollutils.c
+++ b/base/applications/clipbrd/scrollutils.c
@@ -1,202 +1,166 @@
/*
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS Clipboard Viewer
- * FILE: base/applications/clipbrd/scrollutils.c
- * PURPOSE: Scrolling related helper functions.
- * PROGRAMMERS: Ricardo Hanke
+ * PROJECT: ReactOS Clipboard Viewer
+ * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE: Scrolling related helper functions.
+ * COPYRIGHT: Copyright 2015-2018 Ricardo Hanke
+ * Copyright 2015-2018 Hermes Belusca-Maito
*/
#include "precomp.h"
-static int InternalSetScrollInfo(HWND hWnd, int nMin, int nMax, UINT nPage, int nPos, int
fnBar)
-{
- SCROLLINFO si;
-
- ZeroMemory(&si, sizeof(si));
- si.cbSize = sizeof(si);
- si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS | SIF_DISABLENOSCROLL;
- si.nMin = nMin;
- si.nMax = nMax;
- si.nPage = nPage;
- si.nPos = nPos;
-
- return SetScrollInfo(hWnd, fnBar, &si, TRUE);
-}
-
-void HandleKeyboardScrollEvents(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+void OnKeyScroll(HWND hWnd, WPARAM wParam, LPARAM lParam, LPSCROLLSTATE state)
{
+ // NOTE: Windows uses an offset of 16 pixels
switch (wParam)
{
case VK_UP:
- {
- SendMessage(hWnd, WM_VSCROLL, MAKELONG(SB_LINEUP, 0), 0);
+ OnScroll(hWnd, SB_VERT, MAKELONG(SB_LINEUP, 0), 5, state);
break;
- }
case VK_DOWN:
- {
- SendMessage(hWnd, WM_VSCROLL, MAKELONG(SB_LINEDOWN, 0), 0);
+ OnScroll(hWnd, SB_VERT, MAKELONG(SB_LINEDOWN, 0), 5, state);
break;
- }
case VK_LEFT:
- {
- SendMessage(hWnd, WM_HSCROLL, MAKELONG(SB_LINEUP, 0), 0);
+ OnScroll(hWnd, SB_HORZ, MAKELONG(SB_LINELEFT, 0), 5, state);
break;
- }
case VK_RIGHT:
- {
- SendMessage(hWnd, WM_HSCROLL, MAKELONG(SB_LINEDOWN, 0), 0);
+ OnScroll(hWnd, SB_HORZ, MAKELONG(SB_LINERIGHT, 0), 5, state);
break;
- }
case VK_PRIOR:
- {
- SendMessage(hWnd, WM_VSCROLL, MAKELONG(SB_PAGEUP, 0), 0);
+ OnScroll(hWnd, SB_VERT, MAKELONG(SB_PAGEUP, 0), state->nPageY, state);
break;
- }
case VK_NEXT:
+ OnScroll(hWnd, SB_VERT, MAKELONG(SB_PAGEDOWN, 0), state->nPageY, state);
+ break;
+
+ case VK_HOME:
{
- SendMessage(hWnd, WM_VSCROLL, MAKELONG(SB_PAGEDOWN, 0), 0);
+ OnScroll(hWnd, SB_HORZ, MAKELONG(SB_LEFT, 0), 0, state);
+ if (GetKeyState(VK_CONTROL) & 0x8000)
+ OnScroll(hWnd, SB_VERT, MAKELONG(SB_TOP, 0), 0, state);
break;
}
- default:
+ case VK_END:
{
+ OnScroll(hWnd, SB_HORZ, MAKELONG(SB_RIGHT, 0), 0, state);
+ if (GetKeyState(VK_CONTROL) & 0x8000)
+ OnScroll(hWnd, SB_VERT, MAKELONG(SB_BOTTOM, 0), 0, state);
break;
}
+
+ default:
+ break;
}
}
-void HandleMouseScrollEvents(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
LPSCROLLSTATE state)
+void OnMouseScroll(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LPSCROLLSTATE
state)
{
- SCROLLINFO si;
- int Delta;
- int NewPos;
+ INT nBar;
+ INT nPage;
+ INT iDelta;
+ UINT uLinesToScroll = state->uLinesToScroll;
+ INT zDelta = GET_WHEEL_DELTA_WPARAM(wParam);
+ WORD sbCode;
- si.cbSize = sizeof(si);
- si.fMask = SIF_PAGE;
- GetScrollInfo(hWnd, SB_VERT, &si);
+ assert(uMsg == WM_MOUSEWHEEL || uMsg == WM_MOUSEHWHEEL);
- if (Globals.uLinesToScroll == WHEEL_PAGESCROLL)
+ if (uMsg == WM_MOUSEWHEEL)
{
- NewPos = si.nPage;
+ nBar = SB_VERT;
+ nPage = state->nPageY;
+
+ /* Accumulate wheel rotation ticks */
+ zDelta += state->iWheelCarryoverY;
+ state->iWheelCarryoverY = zDelta % WHEEL_DELTA;
}
- else
+ else // if (uMsg == WM_MOUSEHWHEEL)
{
- NewPos = Globals.uLinesToScroll * 5;
+ nBar = SB_HORZ;
+ nPage = state->nPageX;
+
+ /* Accumulate wheel rotation ticks */
+ zDelta += state->iWheelCarryoverX;
+ state->iWheelCarryoverX = zDelta % WHEEL_DELTA;
}
- if (GET_WHEEL_DELTA_WPARAM(wParam) > 0)
+ /*
+ * If the user specified scrolling by pages, do so.
+ * Due to a bug on Windows where, if the window height is
+ * less than the scroll lines delta default value (== 3),
+ * several lines would be skipped when scrolling if we
+ * used the WHEEL_PAGESCROLL value. Instead of this, use
+ * the number of lines per page as the limiting value.
+ * See
https://www.strchr.com/corrections_to_raymond_chen_s_wheel_scrolling_code
+ * for more details.
+ */
+ if (uLinesToScroll > nPage) // (uLinesToScroll == WHEEL_PAGESCROLL)
+ uLinesToScroll = nPage;
+ /* If the user specified no wheel scrolling, don't do anything */
+ else if (uLinesToScroll == 0)
+ return;
+
+ /* Compute the scroll direction and the absolute delta value */
+ if (zDelta > 0)
{
- NewPos = state->CurrentY - NewPos;
+ sbCode = SB_LINEUP;
}
else
{
- NewPos = state->CurrentY + NewPos;
- }
-
- NewPos = min(state->MaxY, max(0, NewPos));
-
- if (NewPos == state->CurrentY)
- {
- return;
+ sbCode = SB_LINEDOWN;
+ zDelta = -zDelta;
}
- Delta = NewPos - state->CurrentY;
-
- state->CurrentY = NewPos;
+ /* Compute how many lines we should scroll (in absolute value) */
+ iDelta = (INT)uLinesToScroll * zDelta / WHEEL_DELTA;
- ScrollWindowEx(hWnd, 0, -Delta, NULL, NULL, NULL, NULL, SW_INVALIDATE);
-
- si.cbSize = sizeof(si);
- si.fMask = SIF_POS;
- si.nPos = state->CurrentY;
- SetScrollInfo(hWnd, SB_VERT, &si, TRUE);
+ OnScroll(hWnd, nBar, MAKELONG(sbCode, 0), iDelta, state);
}
-void HandleHorizontalScrollEvents(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
LPSCROLLSTATE state)
+void OnScroll(HWND hWnd, INT nBar, WPARAM wParam, INT iDelta, LPSCROLLSTATE state)
{
SCROLLINFO si;
- int Delta;
- int NewPos;
+ PINT pCurrent;
+ INT Maximum;
+ INT NewPos;
+ INT OldX, OldY;
- ZeroMemory(&si, sizeof(si));
- si.cbSize = sizeof(si);
- si.fMask = SIF_PAGE | SIF_TRACKPOS;
- GetScrollInfo(hWnd, SB_HORZ, &si);
+ assert(nBar == SB_HORZ || nBar == SB_VERT);
- switch (LOWORD(wParam))
+ if (Globals.uDisplayFormat == CF_OWNERDISPLAY)
{
- case SB_THUMBPOSITION:
- case SB_THUMBTRACK:
+ if (nBar == SB_HORZ)
{
- NewPos = si.nTrackPos;
- break;
+ SendClipboardOwnerMessage(TRUE, WM_HSCROLLCLIPBOARD,
+ (WPARAM)hWnd, (LPARAM)wParam);
}
-
- case SB_LINELEFT:
+ else // if (nBar == SB_VERT)
{
- NewPos = state->CurrentX - 5;
- break;
- }
-
- case SB_LINERIGHT:
- {
- NewPos = state->CurrentX + 5;
- break;
- }
-
- case SB_PAGELEFT:
- {
- NewPos = state->CurrentX - si.nPage;
- break;
- }
-
- case SB_PAGERIGHT:
- {
- NewPos = state->CurrentX + si.nPage;
- break;
- }
-
- default:
- {
- NewPos = state->CurrentX;
- break;
+ SendClipboardOwnerMessage(TRUE, WM_VSCROLLCLIPBOARD,
+ (WPARAM)hWnd, (LPARAM)wParam);
}
+ return;
}
- NewPos = min(state->MaxX, max(0, NewPos));
-
- if (NewPos == state->CurrentX)
- {
- return;
- }
-
- Delta = NewPos - state->CurrentX;
-
- state->CurrentX = NewPos;
-
- ScrollWindowEx(hWnd, -Delta, 0, NULL, NULL, NULL, NULL, SW_INVALIDATE);
-
- si.cbSize = sizeof(si);
- si.fMask = SIF_POS;
- si.nPos = state->CurrentX;
- SetScrollInfo(hWnd, SB_HORZ, &si, TRUE);
-}
-
-void HandleVerticalScrollEvents(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
LPSCROLLSTATE state)
-{
- SCROLLINFO si;
- int Delta;
- int NewPos;
+ if (nBar == SB_HORZ)
+ {
+ pCurrent = &state->CurrentX;
+ Maximum = state->MaxX;
+ }
+ else // if (nBar == SB_VERT)
+ {
+ pCurrent = &state->CurrentY;
+ Maximum = state->MaxY;
+ }
ZeroMemory(&si, sizeof(si));
si.cbSize = sizeof(si);
- si.fMask = SIF_PAGE | SIF_TRACKPOS;
- GetScrollInfo(hWnd, SB_VERT, &si);
+ si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS;
+ GetScrollInfo(hWnd, nBar, &si);
switch (LOWORD(wParam))
{
@@ -207,108 +171,117 @@ void HandleVerticalScrollEvents(HWND hWnd, UINT uMsg, WPARAM
wParam, LPARAM lPar
break;
}
- case SB_LINEUP:
+ case SB_LINEUP: // SB_LINELEFT:
{
- NewPos = state->CurrentY - 5;
+ NewPos = si.nPos - iDelta;
break;
}
- case SB_LINEDOWN:
+ case SB_LINEDOWN: // SB_LINERIGHT:
{
- NewPos = state->CurrentY + 5;
+ NewPos = si.nPos + iDelta;
break;
}
- case SB_PAGEUP:
+ case SB_PAGEUP: // SB_PAGELEFT:
{
- NewPos = state->CurrentY - si.nPage;
+ NewPos = si.nPos - si.nPage;
break;
}
- case SB_PAGEDOWN:
+ case SB_PAGEDOWN: // SB_PAGERIGHT:
{
- NewPos = state->CurrentY + si.nPage;
+ NewPos = si.nPos + si.nPage;
break;
}
- default:
+ case SB_TOP: // SB_LEFT:
{
- NewPos = state->CurrentY;
+ NewPos = si.nMin;
break;
}
- }
- NewPos = min(state->MaxY, max(0, NewPos));
+ case SB_BOTTOM: // SB_RIGHT:
+ {
+ NewPos = si.nMax;
+ break;
+ }
- if (NewPos == state->CurrentY)
- {
- return;
- }
+ default:
+ {
+ NewPos = si.nPos;
+ break;
+ }
+ }
+
+ NewPos = min(max(NewPos, 0), Maximum);
- Delta = NewPos - state->CurrentY;
+ if (si.nPos == NewPos)
+ return;
- state->CurrentY = NewPos;
+ OldX = state->CurrentX;
+ OldY = state->CurrentY;
+ *pCurrent = NewPos;
- ScrollWindowEx(hWnd, 0, -Delta, NULL, NULL, NULL, NULL, SW_INVALIDATE);
+ ScrollWindowEx(hWnd,
+ OldX - state->CurrentX,
+ OldY - state->CurrentY,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ SW_ERASE | SW_INVALIDATE);
+ UpdateWindow(hWnd);
- si.cbSize = sizeof(si);
- si.fMask = SIF_POS;
- si.nPos = state->CurrentY;
- SetScrollInfo(hWnd, SB_VERT, &si, TRUE);
+ si.fMask = SIF_POS;
+ si.nPos = NewPos;
+ SetScrollInfo(hWnd, nBar, &si, TRUE);
}
-void UpdateWindowScrollState(HWND hWnd, HBITMAP hBitmap, LPSCROLLSTATE lpState)
+void UpdateLinesToScroll(LPSCROLLSTATE state)
{
- BITMAP bmp;
- RECT rc;
+ UINT uLinesToScroll;
- if (!GetObject(hBitmap, sizeof(BITMAP), &bmp))
+ if (!SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &uLinesToScroll, 0))
{
- bmp.bmWidth = 0;
- bmp.bmHeight = 0;
+ /* Default value on Windows */
+ state->uLinesToScroll = 3;
}
-
- if (!GetClientRect(hWnd, &rc))
+ else
{
- SetRectEmpty(&rc);
+ state->uLinesToScroll = uLinesToScroll;
}
-
- lpState->MaxX = max(bmp.bmWidth - rc.right, 0);
- lpState->CurrentX = min(lpState->CurrentX, lpState->MaxX);
- InternalSetScrollInfo(hWnd, 0, bmp.bmWidth, rc.right, lpState->CurrentX,
SB_HORZ);
-
- lpState->MaxY = max(bmp.bmHeight - rc.bottom, 0);
- lpState->CurrentY = min(lpState->CurrentY, lpState->MaxY);
- InternalSetScrollInfo(hWnd, 0, bmp.bmHeight, rc.bottom, lpState->CurrentY,
SB_VERT);
}
-BOOL ScrollBlt(PAINTSTRUCT ps, HBITMAP hBmp, SCROLLSTATE state)
+void UpdateWindowScrollState(HWND hWnd, INT nMaxWidth, INT nMaxHeight, LPSCROLLSTATE
lpState)
{
- RECT rect;
- BOOL ret;
- HDC hdc;
- int xpos;
- int ypos;
-
- rect.left = ps.rcPaint.left;
- rect.top = ps.rcPaint.top;
- rect.right = (ps.rcPaint.right - ps.rcPaint.left);
- rect.bottom = (ps.rcPaint.bottom - ps.rcPaint.top);
-
- xpos = ps.rcPaint.left + state.CurrentX;
- ypos = ps.rcPaint.top + state.CurrentY;
+ RECT rc;
+ SCROLLINFO si;
- ret = FALSE;
+ if (!GetClientRect(hWnd, &rc))
+ SetRectEmpty(&rc);
- hdc = CreateCompatibleDC(ps.hdc);
- if (hdc)
- {
- if (SelectObject(hdc, hBmp))
- {
- ret = BitBlt(ps.hdc, rect.left, rect.top, rect.right, rect.bottom, hdc, xpos,
ypos, SRCCOPY);
- }
- DeleteDC(hdc);
- }
+ ZeroMemory(&si, sizeof(si));
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS | SIF_DISABLENOSCROLL;
- return ret;
+ lpState->nMaxWidth = nMaxWidth;
+ lpState->MaxX = max(nMaxWidth - rc.right, 0);
+ lpState->CurrentX = min(lpState->CurrentX, lpState->MaxX);
+ lpState->nPageX = rc.right;
+ si.nMin = 0;
+ si.nMax = nMaxWidth;
+ si.nPage = lpState->nPageX;
+ si.nPos = lpState->CurrentX;
+ SetScrollInfo(hWnd, SB_HORZ, &si, TRUE);
+
+ lpState->nMaxHeight = nMaxHeight;
+ lpState->MaxY = max(nMaxHeight - rc.bottom, 0);
+ lpState->CurrentY = min(lpState->CurrentY, lpState->MaxY);
+ lpState->nPageY = rc.bottom;
+ si.nMin = 0;
+ si.nMax = nMaxHeight;
+ si.nPage = lpState->nPageY;
+ si.nPos = lpState->CurrentY;
+ SetScrollInfo(hWnd, SB_VERT, &si, TRUE);
}
diff --git a/base/applications/clipbrd/scrollutils.h
b/base/applications/clipbrd/scrollutils.h
index 221bf50ce0..4645a24441 100644
--- a/base/applications/clipbrd/scrollutils.h
+++ b/base/applications/clipbrd/scrollutils.h
@@ -1,22 +1,31 @@
/*
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS Clipboard Viewer
- * FILE: base/applications/clipbrd/scrollutils.h
- * PURPOSE: Scrolling related helper functions.
- * PROGRAMMERS: Ricardo Hanke
+ * PROJECT: ReactOS Clipboard Viewer
+ * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE: Scrolling related helper functions.
+ * COPYRIGHT: Copyright 2015-2018 Ricardo Hanke
+ * Copyright 2015-2018 Hermes Belusca-Maito
*/
+#pragma once
+
typedef struct _SCROLLSTATE
{
- int CurrentX;
- int CurrentY;
- int MaxX;
- int MaxY;
+ UINT uLinesToScroll; /* Number of lines to scroll on one wheel rotation movement
(== one "click" == WHEEL_DELTA ticks) */
+ INT iWheelCarryoverX; /* Unused wheel ticks (< WHEEL_DELTA) */
+ INT iWheelCarryoverY;
+ INT nPageX; /* Number of lines per page */
+ INT nPageY;
+ INT CurrentX; /* Current scrollbar position */
+ INT CurrentY;
+ INT MaxX; /* Maximum scrollbar position */
+ INT MaxY;
+ INT nMaxWidth; /* Maximum span of displayed data */
+ INT nMaxHeight;
} SCROLLSTATE, *LPSCROLLSTATE;
-void HandleKeyboardScrollEvents(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
-void HandleMouseScrollEvents(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
LPSCROLLSTATE state);
-void HandleHorizontalScrollEvents(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
LPSCROLLSTATE state);
-void HandleVerticalScrollEvents(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
LPSCROLLSTATE state);
-void UpdateWindowScrollState(HWND hWnd, HBITMAP hBmp, LPSCROLLSTATE lpState);
-BOOL ScrollBlt(PAINTSTRUCT ps, HBITMAP hBmp, SCROLLSTATE state);
+void OnKeyScroll(HWND hWnd, WPARAM wParam, LPARAM lParam, LPSCROLLSTATE state);
+void OnMouseScroll(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LPSCROLLSTATE
state);
+void OnScroll(HWND hWnd, INT nBar, WPARAM wParam, INT iDelta, LPSCROLLSTATE state);
+
+void UpdateLinesToScroll(LPSCROLLSTATE state);
+void UpdateWindowScrollState(HWND hWnd, INT nMaxWidth, INT nMaxHeight, LPSCROLLSTATE
lpState);
diff --git a/base/applications/clipbrd/winutils.c b/base/applications/clipbrd/winutils.c
index 43697d53e9..eb1cf03c2d 100644
--- a/base/applications/clipbrd/winutils.c
+++ b/base/applications/clipbrd/winutils.c
@@ -1,9 +1,9 @@
/*
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS Clipboard Viewer
- * FILE: base/applications/clipbrd/winutils.c
- * PURPOSE: Miscellaneous helper functions.
- * PROGRAMMERS: Ricardo Hanke
+ * PROJECT: ReactOS Clipboard Viewer
+ * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE: Display helper functions.
+ * COPYRIGHT: Copyright 2015-2018 Ricardo Hanke
+ * Copyright 2015-2018 Hermes Belusca-Maito
*/
#include "precomp.h"
@@ -46,22 +46,6 @@ void BringWindowToFront(HWND hWnd)
}
}
-int DrawTextFromResource(HINSTANCE hInstance, UINT uID, HDC hDC, LPRECT lpRect, UINT
uFormat)
-{
- LPWSTR lpBuffer;
- int nCount;
-
- nCount = LoadStringW(hInstance, uID, (LPWSTR)&lpBuffer, 0);
- if (nCount)
- {
- return DrawTextW(hDC, lpBuffer, nCount, lpRect, uFormat);
- }
- else
- {
- return 0;
- }
-}
-
int MessageBoxRes(HWND hWnd, HINSTANCE hInstance, UINT uText, UINT uCaption, UINT uType)
{
MSGBOXPARAMSW mb;
@@ -78,45 +62,135 @@ int MessageBoxRes(HWND hWnd, HINSTANCE hInstance, UINT uText, UINT
uCaption, UIN
return MessageBoxIndirectW(&mb);
}
-void DrawTextFromClipboard(HDC hDC, LPRECT lpRect, UINT uFormat)
+void DrawTextFromResource(HINSTANCE hInstance, UINT uID, HDC hDC, LPRECT lpRect, UINT
uFormat)
{
+ LPWSTR lpBuffer;
+ int nCount;
+
+ nCount = LoadStringW(hInstance, uID, (LPWSTR)&lpBuffer, 0);
+ if (nCount)
+ DrawTextW(hDC, lpBuffer, nCount, lpRect, uFormat);
+}
+
+void DrawTextFromClipboard(UINT uFormat, PAINTSTRUCT ps, SCROLLSTATE state)
+{
+ POINT ptOrg;
HGLOBAL hGlobal;
- LPWSTR lpchText;
+ PVOID lpText, ptr;
+ SIZE_T lineSize;
+ INT FirstLine, LastLine;
- hGlobal = GetClipboardData(CF_UNICODETEXT);
+ hGlobal = GetClipboardData(uFormat);
if (!hGlobal)
return;
- lpchText = GlobalLock(hGlobal);
- if (!lpchText)
+ lpText = GlobalLock(hGlobal);
+ if (!lpText)
return;
- DrawTextW(hDC, lpchText, -1, lpRect, uFormat);
+ /* Find the first and last line indices to display (Note that CurrentX/Y are in
pixels!) */
+ FirstLine = max(0, (state.CurrentY + ps.rcPaint.top) / Globals.CharHeight);
+ // LastLine = min(LINES - 1, (state.CurrentY + ps.rcPaint.bottom) /
Globals.CharHeight);
+ // NOTE: Can be less or greater than the actual number of lines in the text.
+ LastLine = (state.CurrentY + ps.rcPaint.bottom) / Globals.CharHeight;
+
+ /* Find the first text line to display */
+ while (FirstLine > 0)
+ {
+ if (uFormat == CF_UNICODETEXT)
+ {
+ if (*(LPCWSTR)lpText == UNICODE_NULL)
+ break;
+ GetLineExtentW(lpText, (LPCWSTR*)&ptr);
+ }
+ else
+ {
+ if (*(LPCSTR)lpText == ANSI_NULL)
+ break;
+ GetLineExtentA(lpText, (LPCSTR*)&ptr);
+ }
+
+ --FirstLine;
+ --LastLine;
+
+ lpText = ptr;
+ }
+
+ ptOrg.x = ps.rcPaint.left;
+ ptOrg.y = /* FirstLine */ max(0, (state.CurrentY + ps.rcPaint.top) /
Globals.CharHeight)
+ * Globals.CharHeight - state.CurrentY;
+
+ /* Display each line from the current one up to the last one */
+ ++LastLine;
+ while (LastLine >= 0)
+ {
+ if (uFormat == CF_UNICODETEXT)
+ {
+ if (*(LPCWSTR)lpText == UNICODE_NULL)
+ break;
+ lineSize = GetLineExtentW(lpText, (LPCWSTR*)&ptr);
+ TabbedTextOutW(ps.hdc, /*ptOrg.x*/0 - state.CurrentX, ptOrg.y,
+ lpText, lineSize, 0, NULL,
+ /*ptOrg.x*/0 - state.CurrentX);
+ }
+ else
+ {
+ if (*(LPCSTR)lpText == ANSI_NULL)
+ break;
+ lineSize = GetLineExtentA(lpText, (LPCSTR*)&ptr);
+ TabbedTextOutA(ps.hdc, /*ptOrg.x*/0 - state.CurrentX, ptOrg.y,
+ lpText, lineSize, 0, NULL,
+ /*ptOrg.x*/0 - state.CurrentX);
+ }
+
+ --LastLine;
+
+ ptOrg.y += Globals.CharHeight;
+ lpText = ptr;
+ }
+
GlobalUnlock(hGlobal);
}
-void BitBltFromClipboard(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight,
int nXSrc, int nYSrc, DWORD dwRop)
+void BitBltFromClipboard(PAINTSTRUCT ps, SCROLLSTATE state, DWORD dwRop)
{
HDC hdcMem;
- HBITMAP hbm;
+ HBITMAP hBitmap;
+ BITMAP bmp;
+ LONG bmWidth, bmHeight;
- hdcMem = CreateCompatibleDC(hdcDest);
- if (hdcMem)
- {
- hbm = (HBITMAP)GetClipboardData(CF_BITMAP);
- SelectObject(hdcMem, hbm);
- BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcMem, nXSrc, nYSrc, dwRop);
- DeleteDC(hdcMem);
- }
+ hdcMem = CreateCompatibleDC(ps.hdc);
+ if (!hdcMem)
+ return;
+
+ hBitmap = (HBITMAP)GetClipboardData(CF_BITMAP);
+ GetObjectW(hBitmap, sizeof(bmp), &bmp);
+
+ SelectObject(hdcMem, hBitmap);
+
+ bmWidth = min(ps.rcPaint.right - ps.rcPaint.left, bmp.bmWidth - ps.rcPaint.left -
state.CurrentX);
+ bmHeight = min(ps.rcPaint.bottom - ps.rcPaint.top , bmp.bmHeight - ps.rcPaint.top -
state.CurrentY);
+
+ BitBlt(ps.hdc,
+ ps.rcPaint.left,
+ ps.rcPaint.top,
+ bmWidth,
+ bmHeight,
+ hdcMem,
+ ps.rcPaint.left + state.CurrentX,
+ ps.rcPaint.top + state.CurrentY,
+ dwRop);
+
+ DeleteDC(hdcMem);
}
-void SetDIBitsToDeviceFromClipboard(UINT uFormat, HDC hdc, int XDest, int YDest, int
XSrc, int YSrc, UINT uStartScan, UINT fuColorUse)
+void SetDIBitsToDeviceFromClipboard(UINT uFormat, PAINTSTRUCT ps, SCROLLSTATE state, UINT
fuColorUse)
{
+ HGLOBAL hGlobal;
LPBITMAPINFOHEADER lpInfoHeader;
LPBYTE lpBits;
LONG bmWidth, bmHeight;
DWORD dwPalSize = 0;
- HGLOBAL hGlobal;
hGlobal = GetClipboardData(uFormat);
if (!hGlobal)
@@ -183,9 +257,9 @@ void SetDIBitsToDeviceFromClipboard(UINT uFormat, HDC hdc, int XDest,
int YDest,
*
* FIXME: investigate!!
* ANSWER: this is a Windows bug; part of the answer is there:
- *
http://go4answers.webhost4life.com/Help/bug-clipboard-format-conversions-28…
+ *
https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/ac7ab3b5-8609…
* May be related:
- *
http://blog.talosintel.com/2015/10/dangerous-clipboard.html
+ *
https://blog.talosintelligence.com/2015/10/dangerous-clipboard.html
*/
#if 0
if ((lpInfoHeader->biSize == sizeof(BITMAPINFOHEADER)) &&
@@ -196,6 +270,7 @@ void SetDIBitsToDeviceFromClipboard(UINT uFormat, HDC hdc, int XDest,
int YDest,
#endif
bmWidth = lpInfoHeader->biWidth;
+ /* NOTE: biHeight < 0 for bottom-up DIBs, or > 0 for top-down DIBs */
bmHeight = lpInfoHeader->biHeight;
}
else
@@ -207,11 +282,19 @@ void SetDIBitsToDeviceFromClipboard(UINT uFormat, HDC hdc, int
XDest, int YDest,
lpBits = (LPBYTE)lpInfoHeader + lpInfoHeader->biSize + dwPalSize;
- SetDIBitsToDevice(hdc,
- XDest, YDest,
- bmWidth, bmHeight,
- XSrc, YSrc,
- uStartScan,
+ /*
+ * The seventh parameter (YSrc) of SetDIBitsToDevice always designates
+ * the Y-coordinate of the "lower-left corner" of the image, be the DIB
+ * in bottom-up or top-down mode.
+ */
+ SetDIBitsToDevice(ps.hdc,
+ -state.CurrentX, // ps.rcPaint.left,
+ -state.CurrentY, // ps.rcPaint.top,
+ bmWidth,
+ bmHeight,
+ 0, // ps.rcPaint.left + state.CurrentX,
+ 0, // -(ps.rcPaint.top + state.CurrentY),
+ 0, // uStartScan,
bmHeight,
lpBits,
(LPBITMAPINFO)lpInfoHeader,
@@ -248,52 +331,25 @@ void PlayEnhMetaFileFromClipboard(HDC hdc, const RECT *lpRect)
PlayEnhMetaFile(hdc, hEmf, lpRect);
}
-UINT RealizeClipboardPalette(HWND hWnd)
+BOOL RealizeClipboardPalette(HDC hdc)
{
- HPALETTE hPalette;
- HPALETTE hOldPalette;
- UINT uResult;
- HDC hDevContext;
-
- if (!OpenClipboard(Globals.hMainWnd))
- {
- return GDI_ERROR;
- }
+ BOOL Success;
+ HPALETTE hPalette, hOldPalette;
if (!IsClipboardFormatAvailable(CF_PALETTE))
- {
- CloseClipboard();
- return GDI_ERROR;
- }
+ return FALSE;
hPalette = GetClipboardData(CF_PALETTE);
if (!hPalette)
- {
- CloseClipboard();
- return GDI_ERROR;
- }
-
- hDevContext = GetDC(hWnd);
- if (!hDevContext)
- {
- CloseClipboard();
- return GDI_ERROR;
- }
+ return FALSE;
- hOldPalette = SelectPalette(hDevContext, hPalette, FALSE);
+ hOldPalette = SelectPalette(hdc, hPalette, FALSE);
if (!hOldPalette)
- {
- ReleaseDC(hWnd, hDevContext);
- CloseClipboard();
- return GDI_ERROR;
- }
-
- uResult = RealizePalette(hDevContext);
+ return FALSE;
- SelectPalette(hDevContext, hOldPalette, FALSE);
- ReleaseDC(hWnd, hDevContext);
+ Success = (RealizePalette(hdc) != GDI_ERROR);
- CloseClipboard();
+ SelectPalette(hdc, hOldPalette, FALSE);
- return uResult;
+ return Success;
}
diff --git a/base/applications/clipbrd/winutils.h b/base/applications/clipbrd/winutils.h
index 12dde908d8..e29ec927bc 100644
--- a/base/applications/clipbrd/winutils.h
+++ b/base/applications/clipbrd/winutils.h
@@ -1,18 +1,20 @@
/*
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS Clipboard Viewer
- * FILE: base/applications/clipbrd/winutils.h
- * PURPOSE: Miscellaneous helper functions.
- * PROGRAMMERS: Ricardo Hanke
+ * PROJECT: ReactOS Clipboard Viewer
+ * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE: Display helper functions.
+ * COPYRIGHT: Copyright 2015-2018 Ricardo Hanke
+ * Copyright 2015-2018 Hermes Belusca-Maito
*/
+#pragma once
+
void ShowLastWin32Error(HWND hwndParent);
void BringWindowToFront(HWND hWnd);
-int DrawTextFromResource(HINSTANCE hInstance, UINT uID, HDC hDC, LPRECT lpRect, UINT
uFormat);
int MessageBoxRes(HWND hWnd, HINSTANCE hInstance, UINT uText, UINT uCaption, UINT
uType);
-void DrawTextFromClipboard(HDC hDC, LPRECT lpRect, UINT uFormat);
-void BitBltFromClipboard(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight,
int nXSrc, int nYSrc, DWORD dwRop);
-void SetDIBitsToDeviceFromClipboard(UINT uFormat, HDC hdc, int XDest, int YDest, int
XSrc, int YSrc, UINT uStartScan, UINT fuColorUse);
+void DrawTextFromResource(HINSTANCE hInstance, UINT uID, HDC hDC, LPRECT lpRect, UINT
uFormat);
+void DrawTextFromClipboard(UINT uFormat, PAINTSTRUCT ps, SCROLLSTATE state);
+void BitBltFromClipboard(PAINTSTRUCT ps, SCROLLSTATE state, DWORD dwRop);
+void SetDIBitsToDeviceFromClipboard(UINT uFormat, PAINTSTRUCT ps, SCROLLSTATE state, UINT
fuColorUse);
void PlayMetaFileFromClipboard(HDC hdc, const RECT *lpRect);
void PlayEnhMetaFileFromClipboard(HDC hdc, const RECT *lpRect);
-UINT RealizeClipboardPalette(HWND hWnd);
+BOOL RealizeClipboardPalette(HDC hdc);