755 lines
27 KiB
C++
755 lines
27 KiB
C++
#define NTDDI_VERSION 0x06030000
|
|
|
|
#include <algorithm>
|
|
#include <iostream>
|
|
#include <windows.h>
|
|
#include <windowsx.h>
|
|
#include <shellscalingapi.h>
|
|
#include <vector>
|
|
|
|
#define WM_UPDATE_SIZE (WM_USER + 1)
|
|
//#define SPECIAL_COLOR RGB(239, 228, 176)
|
|
#define SPECIAL_COLOR RGB(255, 0, 0)
|
|
|
|
HINSTANCE instance;
|
|
HWND mainWindow;
|
|
HWND createButton;
|
|
HBITMAP bmpTarget;
|
|
HBITMAP captured = NULL;
|
|
int capturedWidth;
|
|
int capturedHeight;
|
|
|
|
HWND penButton;
|
|
HWND markerButton;
|
|
HWND widePenButton;
|
|
HWND specialButton;
|
|
|
|
RECT dragRect = {};
|
|
BOOLEAN dragging = FALSE;
|
|
int lastMouseX = 0;
|
|
int lastMouseY = 0;
|
|
|
|
enum Tool {
|
|
NONE,
|
|
PEN,
|
|
MARKER,
|
|
WIDE_PEN,
|
|
SPECIAL
|
|
};
|
|
Tool currentTool = NONE;
|
|
UINT8 penSize = 10;
|
|
UINT8 markerSize = 10;
|
|
UINT8 widePenSize = 10;
|
|
COLORREF penColor = RGB(255, 0, 0);
|
|
COLORREF markerColor = RGB(255, 255, 0);
|
|
COLORREF widePenColor = RGB(0, 0, 0);
|
|
std::vector<RECT> currentMarkings = std::vector<RECT>();
|
|
BOOLEAN marking = FALSE;
|
|
COLORREF customColors[16] = {};
|
|
|
|
enum SpecialPhase {
|
|
FIRST_START,
|
|
FIRST_END,
|
|
SECOND_START,
|
|
SECOND_END,
|
|
FIRST_DIRECTION,
|
|
SECOND_DIRECTION,
|
|
};
|
|
enum Direction {
|
|
LEFT,
|
|
RIGHT,
|
|
BOTTOM,
|
|
TOP
|
|
};
|
|
SpecialPhase specialPhase;
|
|
RECT firstLine;
|
|
RECT secondLine;
|
|
Direction firstDirection;
|
|
Direction secondDirection;
|
|
|
|
DWORD getRGBA(int alpha, int r, int g, int b) {
|
|
return (BYTE) alpha | (WORD)(BYTE) r << 8 | (DWORD)(BYTE) g << 16 | (DWORD)(BYTE) b << 24;
|
|
}
|
|
|
|
void makeLine(LPRECT rect, int mouseX, int mouseY) {
|
|
int xDiff = mouseX - rect->left;
|
|
int yDiff = mouseY - rect->top;
|
|
if (xDiff >= yDiff) {
|
|
rect->right = mouseX;
|
|
rect->bottom = rect->top + 2;
|
|
} else {
|
|
rect->bottom = mouseY;
|
|
rect->right = rect->left + 2;
|
|
}
|
|
}
|
|
|
|
void makeDirection(Direction *direction, RECT line, int mouseX, int mouseY) {
|
|
if (mouseX < line.left) {
|
|
*direction = LEFT;
|
|
} else if (mouseX > line.right) {
|
|
*direction = RIGHT;
|
|
} else if (mouseY < line.top) {
|
|
*direction = TOP;
|
|
} else {
|
|
*direction = BOTTOM;
|
|
}
|
|
}
|
|
|
|
BLENDFUNCTION getBlendFunction(BYTE alpha) {
|
|
BLENDFUNCTION blend = {};
|
|
blend.BlendOp = AC_SRC_OVER;
|
|
blend.AlphaFormat = AC_SRC_ALPHA;
|
|
blend.SourceConstantAlpha = alpha;
|
|
return blend;
|
|
}
|
|
|
|
void setTool(Tool tool) {
|
|
Button_SetState(penButton, tool == PEN);
|
|
Button_SetState(markerButton, tool == MARKER);
|
|
Button_SetState(widePenButton, tool == WIDE_PEN);
|
|
Button_SetState(specialButton, tool == SPECIAL);
|
|
currentTool = tool;
|
|
if (tool == SPECIAL) {
|
|
specialPhase = FIRST_START;
|
|
firstLine = {};
|
|
secondLine = {};
|
|
firstDirection = LEFT;
|
|
secondDirection = LEFT;
|
|
}
|
|
InvalidateRect(mainWindow, NULL, FALSE); //Color Selector
|
|
}
|
|
|
|
void drawPen(HDC hdc, int x, int y) {
|
|
if (penSize > 0) {
|
|
SelectObject(hdc, GetStockObject(DC_BRUSH));
|
|
SelectObject(hdc, GetStockObject(DC_PEN));
|
|
SetDCBrushColor(hdc, penColor);
|
|
SetDCPenColor(hdc, penColor);
|
|
|
|
Ellipse(hdc, x - penSize, y - penSize, x + penSize + 1, y + penSize + 1);
|
|
} else {
|
|
RECT rect;
|
|
rect.left = x;
|
|
rect.top = y;
|
|
rect.right = x + 1;
|
|
rect.bottom = y + 1;
|
|
HBRUSH brush = CreateSolidBrush(penColor);
|
|
|
|
FillRect(hdc, &rect, brush);
|
|
DeleteBrush(brush);
|
|
}
|
|
}
|
|
|
|
void addMarker(int x, int y) {
|
|
RECT rect;
|
|
rect.left = x - 3;
|
|
rect.top = y - markerSize / 2;
|
|
rect.right = x + 5;
|
|
rect.bottom = y + markerSize / 2;
|
|
currentMarkings.push_back(rect);
|
|
}
|
|
|
|
void drawMarker(HDC hdc, int offsetX, int offsetY) {
|
|
HDC solidDC = CreateCompatibleDC(hdc);
|
|
|
|
BITMAPINFO info = {};
|
|
info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
|
info.bmiHeader.biWidth = capturedWidth;
|
|
info.bmiHeader.biHeight = -capturedHeight;
|
|
info.bmiHeader.biPlanes = 1;
|
|
info.bmiHeader.biBitCount = 32;
|
|
info.bmiHeader.biCompression = BI_RGB;
|
|
void* bits;
|
|
HBITMAP tempBmp = CreateDIBSection(hdc, &info, DIB_RGB_COLORS, &bits, nullptr, 0);
|
|
memset(bits, 0, capturedWidth * capturedHeight * 4);
|
|
HGDIOBJ oldObj = SelectObject(solidDC, tempBmp);
|
|
|
|
DWORD* px = (DWORD*)bits;
|
|
for (RECT rect : currentMarkings) {
|
|
for (int y = std::max(0L, rect.top); y < std::min(capturedHeight, (int) rect.bottom); y++) {
|
|
for (int x = std::max(0L, rect.left); x < std::min(capturedWidth, (int) rect.right); x++) {
|
|
px[y * capturedWidth + x] = 0xFF000000 | ((DWORD)GetRValue(markerColor) << 16) | ((DWORD)GetGValue(markerColor) << 8) | ((DWORD)GetBValue(markerColor));
|
|
}
|
|
}
|
|
}
|
|
|
|
AlphaBlend(hdc, offsetX, offsetY, capturedWidth, capturedHeight, solidDC, 0, 0, capturedWidth, capturedHeight, getBlendFunction(100));
|
|
|
|
SelectObject(solidDC, oldObj);
|
|
DeleteDC(solidDC);
|
|
DeleteObject(tempBmp);
|
|
}
|
|
|
|
void drawWidePen(HDC hdc, int x, int y) {
|
|
RECT rect;
|
|
rect.left = x - 1;
|
|
rect.top = y - widePenSize / 2;
|
|
rect.right = x + 3;
|
|
rect.bottom = y + widePenSize / 2;
|
|
HBRUSH brush = CreateSolidBrush(widePenColor);
|
|
|
|
FillRect(hdc, &rect, brush);
|
|
DeleteBrush(brush);
|
|
}
|
|
|
|
void drawSpecialLine(HDC hdc, HBRUSH brush, int x, int y, int length, bool vertical, int offsetX, int offsetY) {
|
|
if (length < 0) {
|
|
length = -length;
|
|
if (!vertical) {
|
|
x = x - length;
|
|
} else {
|
|
y = y - length;
|
|
}
|
|
}
|
|
RECT rect;
|
|
rect.left = x + offsetX;
|
|
rect.top = y + offsetY;
|
|
rect.right = x + 1 + offsetX;
|
|
rect.bottom = y + 1 + offsetY;
|
|
if (vertical) {
|
|
rect.right += 2;
|
|
} else {
|
|
rect.bottom += 2;
|
|
}
|
|
for (int i = 0; i < length; i += 2) {
|
|
FillRect(hdc, &rect, brush);
|
|
if (vertical) {
|
|
rect.top += 2;
|
|
rect.bottom += 2;
|
|
} else {
|
|
rect.left += 2;
|
|
rect.right += 2;
|
|
}
|
|
}
|
|
}
|
|
|
|
void drawSpecial(HDC hdc, int offsetX, int offsetY) {
|
|
HBRUSH brush = CreateSolidBrush(SPECIAL_COLOR);
|
|
RECT rect;
|
|
|
|
rect.left = firstLine.left + offsetX;
|
|
rect.top = firstLine.top + offsetY;
|
|
rect.right = firstLine.right + offsetX;
|
|
rect.bottom = firstLine.bottom + offsetY;
|
|
FillRect(hdc, &rect, brush);
|
|
if (specialPhase >= SECOND_END) {
|
|
rect.left = secondLine.left + offsetX;
|
|
rect.top = secondLine.top + offsetY;
|
|
rect.right = secondLine.right + offsetX;
|
|
rect.bottom = secondLine.bottom + offsetY;
|
|
FillRect(hdc, &rect, brush);
|
|
}
|
|
if (specialPhase >= FIRST_DIRECTION) {
|
|
if ((firstDirection == LEFT || firstDirection == RIGHT) && firstDirection == secondDirection) {
|
|
int x;
|
|
if (firstDirection == LEFT) {
|
|
if (firstLine.left <= secondLine.left) {
|
|
x = firstLine.left - 10;
|
|
} else {
|
|
x = secondLine.left - 10;
|
|
}
|
|
} else {
|
|
if (firstLine.right >= secondLine.right) {
|
|
x = firstLine.right + 10;
|
|
} else {
|
|
x = secondLine.right + 10;
|
|
}
|
|
}
|
|
drawSpecialLine(hdc, brush, x, firstLine.top, firstDirection == LEFT ? firstLine.left - x : firstLine.right - x, false, offsetX, offsetY);
|
|
drawSpecialLine(hdc, brush, x, secondLine.top, firstDirection == LEFT ? secondLine.left - x : secondLine.right - x, false, offsetX, offsetY);
|
|
int textY;
|
|
if (firstLine.top <= secondLine.top) {
|
|
int length = secondLine.top - firstLine.top;
|
|
drawSpecialLine(hdc, brush, x, firstLine.top, length, true, offsetX, offsetY);
|
|
textY = firstLine.top + length / 2;
|
|
} else {
|
|
int length = firstLine.top - secondLine.top;
|
|
drawSpecialLine(hdc, brush, x, secondLine.top, length, true, offsetX, offsetY);
|
|
textY = secondLine.top + length / 2;
|
|
}
|
|
RECT rect = {};
|
|
rect.top = textY + offsetY;
|
|
rect.bottom = textY + 100 + offsetY;
|
|
if (firstDirection == LEFT) {
|
|
rect.left = x - 80 + offsetX;
|
|
rect.right = x - 3 + offsetX;
|
|
} else {
|
|
rect.left = x + 3 + offsetX;
|
|
rect.right = x + 80 + offsetX;
|
|
}
|
|
SetTextColor(hdc, SPECIAL_COLOR);
|
|
SetBkColor(hdc, RGB(0, 0, 0));
|
|
//SetBkMode(hdc, TRANSPARENT);
|
|
DrawText(hdc, "Diskrepanz Entdeckt", -1, &rect, DT_WORDBREAK);
|
|
} else {
|
|
if ((firstDirection == BOTTOM && secondDirection == TOP && firstLine.top <= secondLine.top) || (firstDirection == TOP && secondDirection == BOTTOM && secondLine.top <= firstLine.top)) {
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
DeleteBrush(brush);
|
|
}
|
|
|
|
void invalidateImageArea(HWND hWnd) {
|
|
RECT size;
|
|
GetClientRect(hWnd, &size);
|
|
size.top += 35;
|
|
InvalidateRect(hWnd, &size, FALSE);
|
|
}
|
|
|
|
LPCOLORREF getToolColor() {
|
|
LPCOLORREF color;
|
|
if (currentTool == PEN) {
|
|
color = &penColor;
|
|
} else if (currentTool == WIDE_PEN) {
|
|
color = &widePenColor;
|
|
} else {
|
|
color = &markerColor;
|
|
}
|
|
return color;
|
|
}
|
|
|
|
LRESULT WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
|
switch (uMsg) {
|
|
case WM_CREATE: {
|
|
createButton = CreateWindow("Button", "Create", WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 10, 10, 280, 20, hWnd, NULL, instance, NULL);
|
|
PostMessage(hWnd, WM_UPDATE_SIZE, 0, 0);
|
|
return 0;
|
|
}
|
|
case WM_COMMAND: {
|
|
if ((HWND) lParam == createButton) {
|
|
SetWindowPos(hWnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW);
|
|
setTool(NONE);
|
|
|
|
Sleep(333);
|
|
|
|
int x = GetSystemMetrics(SM_XVIRTUALSCREEN); //left (e.g. -1024)
|
|
int y = GetSystemMetrics(SM_YVIRTUALSCREEN); //top (e.g. -34)
|
|
int cx = GetSystemMetrics(SM_CXVIRTUALSCREEN); //entire width (e.g. 2704)
|
|
int cy = GetSystemMetrics(SM_CYVIRTUALSCREEN); //entire height (e.g. 1050)
|
|
|
|
HDC dcScreen = GetDC(NULL);
|
|
HDC dcTarget = CreateCompatibleDC(dcScreen);
|
|
bmpTarget = CreateCompatibleBitmap(dcScreen, cx, cy);
|
|
HGDIOBJ oldObj = SelectObject(dcTarget, bmpTarget);
|
|
BitBlt(dcTarget, 0, 0, cx, cy, dcScreen, x, y, SRCCOPY | CAPTUREBLT);
|
|
SelectObject(dcTarget, oldObj);
|
|
DeleteDC(dcTarget);
|
|
ReleaseDC(NULL, dcScreen);
|
|
|
|
HWND window = CreateWindow("BSnippingToolPreview", "Preview", WS_POPUP | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, instance, NULL);
|
|
SetWindowPos(window, NULL, x, y, cx, cy, SWP_NOZORDER | SWP_FRAMECHANGED);
|
|
} else if ((HWND) lParam == penButton) {
|
|
setTool(PEN);
|
|
} else if ((HWND) lParam == markerButton) {
|
|
setTool(MARKER);
|
|
} else if ((HWND) lParam == widePenButton) {
|
|
setTool(WIDE_PEN);
|
|
} else if ((HWND) lParam == specialButton) {
|
|
setTool(SPECIAL);
|
|
}
|
|
return 0;
|
|
}
|
|
case WM_PAINT: {
|
|
PAINTSTRUCT ps;
|
|
HDC hdc = BeginPaint(hWnd, &ps);
|
|
|
|
RECT size;
|
|
GetClientRect(hWnd, &size);
|
|
int width = size.right - size.left;
|
|
int height = size.bottom - size.top;
|
|
|
|
HDC tempDC = CreateCompatibleDC(hdc);
|
|
HBITMAP tempBmp = CreateCompatibleBitmap(hdc, width, height);
|
|
HGDIOBJ oldObj = SelectObject(tempDC, tempBmp);
|
|
|
|
FillRect(tempDC, &ps.rcPaint, GetSysColorBrush(COLOR_WINDOW));
|
|
if (captured != NULL) {
|
|
HDC sourceDC = CreateCompatibleDC(hdc);
|
|
HGDIOBJ oldObj2 = SelectObject(sourceDC, captured);
|
|
|
|
BitBlt(tempDC, 10, 40, capturedWidth, capturedHeight, sourceDC, 0, 0, SRCCOPY);
|
|
|
|
SelectObject(sourceDC, oldObj2);
|
|
DeleteDC(sourceDC);
|
|
|
|
if (lastMouseY >= 35) {
|
|
if (currentTool == PEN) {
|
|
drawPen(tempDC, lastMouseX, lastMouseY);
|
|
} else if (currentTool == MARKER) {
|
|
if (!marking) {
|
|
addMarker(lastMouseX - 10, lastMouseY - 40);
|
|
drawMarker(tempDC, 10, 40);
|
|
currentMarkings.clear();
|
|
} else {
|
|
drawMarker(tempDC, 10, 40);
|
|
}
|
|
} else if (currentTool == WIDE_PEN) {
|
|
drawWidePen(tempDC, lastMouseX, lastMouseY);
|
|
} else if (currentTool == SPECIAL) {
|
|
if (specialPhase != FIRST_START) {
|
|
if (specialPhase == FIRST_END) {
|
|
makeLine(&firstLine, lastMouseX - 10, lastMouseY - 40);
|
|
} else if (specialPhase == SECOND_END) {
|
|
makeLine(&secondLine, lastMouseX - 10, lastMouseY - 40);
|
|
} else if (specialPhase == FIRST_DIRECTION) {
|
|
makeDirection(&firstDirection, firstLine, lastMouseX - 10, lastMouseY - 40);
|
|
} else if (specialPhase == SECOND_DIRECTION) {
|
|
makeDirection(&secondDirection, secondLine, lastMouseX - 10, lastMouseY - 40);
|
|
}
|
|
drawSpecial(tempDC, 10, 40);
|
|
}
|
|
}
|
|
}
|
|
if (currentTool == PEN || currentTool == WIDE_PEN || currentTool == MARKER) {
|
|
HBRUSH brush = CreateSolidBrush(*getToolColor());
|
|
RECT rect = {};
|
|
rect.left = 350;
|
|
rect.top = 10;
|
|
rect.right = rect.left + 20;
|
|
rect.bottom = rect.top + 20;
|
|
FillRect(tempDC, &rect, brush);
|
|
DeleteBrush(brush);
|
|
}
|
|
}
|
|
|
|
BitBlt(hdc, 0, 0, width, height, tempDC, 0, 0, SRCCOPY);
|
|
SelectObject(tempDC, oldObj);
|
|
DeleteDC(tempDC);
|
|
DeleteObject(tempBmp);
|
|
|
|
EndPaint(hWnd, &ps);
|
|
return 0;
|
|
}
|
|
case WM_UPDATE_SIZE: {
|
|
RECT size = {};
|
|
size.right = 300;
|
|
size.bottom = 40;
|
|
if (captured != NULL) {
|
|
size.right = std::max(380, capturedWidth + 20);
|
|
size.bottom += capturedHeight + 10;
|
|
}
|
|
|
|
AdjustWindowRect(&size, WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, FALSE);
|
|
SetWindowPos(mainWindow, NULL, 0, 0, size.right - size.left, size.bottom - size.top, SWP_NOMOVE | SWP_NOZORDER);
|
|
return 0;
|
|
}
|
|
case WM_MOUSEMOVE:
|
|
lastMouseX = LOWORD(lParam);
|
|
lastMouseY = HIWORD(lParam);
|
|
case WM_LBUTTONDOWN: {
|
|
int relativeY = lastMouseY - 40;
|
|
int relativeX = lastMouseX - 10;
|
|
if (currentTool != NONE) {
|
|
if (wParam == MK_LBUTTON) {
|
|
if (lastMouseX >= 350 && lastMouseX <= 370 && lastMouseY >= 10 && lastMouseY <= 30
|
|
&& (currentTool == PEN || currentTool == WIDE_PEN || currentTool == MARKER)) {
|
|
LPCOLORREF color = getToolColor();
|
|
|
|
CHOOSECOLOR colorSettings = {};
|
|
colorSettings.lStructSize = sizeof(CHOOSECOLOR);
|
|
colorSettings.hwndOwner = hWnd;
|
|
colorSettings.lpCustColors = customColors;
|
|
colorSettings.rgbResult = *color;
|
|
colorSettings.Flags = CC_RGBINIT | CC_FULLOPEN;
|
|
if (ChooseColor(&colorSettings)) {
|
|
*color = colorSettings.rgbResult;
|
|
InvalidateRect(hWnd, NULL, FALSE);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
HDC screenDC = GetDC(NULL);
|
|
HDC sourceDC = CreateCompatibleDC(screenDC);
|
|
HGDIOBJ oldObj = SelectObject(sourceDC, captured);
|
|
|
|
|
|
if (currentTool == PEN) {
|
|
drawPen(sourceDC, relativeX, relativeY);
|
|
} else if (currentTool == MARKER) {
|
|
addMarker(relativeX, relativeY);
|
|
marking = TRUE;
|
|
} else if (currentTool == WIDE_PEN) {
|
|
drawWidePen(sourceDC, relativeX, relativeY);
|
|
} else if (currentTool == SPECIAL) {
|
|
if (specialPhase == FIRST_START) {
|
|
firstLine.left = relativeX;
|
|
firstLine.top = relativeY;
|
|
specialPhase = FIRST_END;
|
|
} else if (specialPhase == FIRST_END) {
|
|
makeLine(&firstLine, relativeX, relativeY);
|
|
specialPhase = SECOND_START;
|
|
} else if (specialPhase == SECOND_START) {
|
|
secondLine.left = relativeX;
|
|
secondLine.top = relativeY;
|
|
specialPhase = SECOND_END;
|
|
} else if (specialPhase == SECOND_END) {
|
|
makeLine(&secondLine, relativeX, relativeY);
|
|
specialPhase = FIRST_DIRECTION;
|
|
} else if (specialPhase == FIRST_DIRECTION) {
|
|
makeDirection(&firstDirection, firstLine, relativeX, relativeY);
|
|
specialPhase = SECOND_DIRECTION;
|
|
} else if (specialPhase == SECOND_DIRECTION) {
|
|
makeDirection(&secondDirection, secondLine, relativeX, relativeY);
|
|
drawSpecial(sourceDC, 0, 0);
|
|
setTool(NONE);
|
|
}
|
|
}
|
|
|
|
SelectObject(sourceDC, oldObj);
|
|
DeleteDC(sourceDC);
|
|
ReleaseDC(NULL, screenDC);
|
|
}
|
|
|
|
invalidateImageArea(hWnd);
|
|
}
|
|
return 0;
|
|
}
|
|
case WM_LBUTTONUP: {
|
|
if (marking) {
|
|
HDC screenDC = GetDC(NULL);
|
|
HDC sourceDC = CreateCompatibleDC(screenDC);
|
|
HGDIOBJ oldObj = SelectObject(sourceDC, captured);
|
|
|
|
marking = FALSE;
|
|
drawMarker(sourceDC, 0, 0);
|
|
currentMarkings.clear();
|
|
|
|
SelectObject(sourceDC, oldObj);
|
|
DeleteDC(sourceDC);
|
|
ReleaseDC(NULL, screenDC);
|
|
}
|
|
}
|
|
case WM_MOUSEWHEEL: {
|
|
int change = (short) HIWORD(wParam) / WHEEL_DELTA;
|
|
if (currentTool == PEN) {
|
|
penSize += change;
|
|
invalidateImageArea(hWnd);
|
|
} else if (currentTool == MARKER) {
|
|
markerSize += change;
|
|
invalidateImageArea(hWnd);
|
|
} else if (currentTool == WIDE_PEN) {
|
|
widePenSize += change * 2;
|
|
invalidateImageArea(hWnd);
|
|
}
|
|
return 0;
|
|
}
|
|
case WM_CONTEXTMENU: {
|
|
int x = GET_X_LPARAM(lParam);
|
|
int y = GET_Y_LPARAM(lParam);
|
|
HMENU menu = CreatePopupMenu();
|
|
AppendMenu(menu, MF_STRING, 1, TEXT("Copy"));
|
|
BOOL clicked = TrackPopupMenu(menu, TPM_RETURNCMD, x, y, NULL, hWnd, NULL);
|
|
if (clicked) {
|
|
if (OpenClipboard(hWnd)) {
|
|
EmptyClipboard();
|
|
BITMAP bm;
|
|
if (!GetObject(captured, sizeof(bm), &bm))
|
|
return false;
|
|
|
|
BITMAPINFOHEADER bi = {};
|
|
bi.biSize = sizeof(bi);
|
|
bi.biWidth = bm.bmWidth;
|
|
bi.biHeight = bm.bmHeight;
|
|
bi.biPlanes = 1;
|
|
bi.biBitCount = 32;
|
|
bi.biCompression = BI_RGB;
|
|
|
|
int stride = ((bi.biWidth * 32 + 31) / 32) * 4;
|
|
DWORD size = stride * bi.biHeight;
|
|
|
|
HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, sizeof(bi) + size);
|
|
if (hMem) {
|
|
BYTE* p = (BYTE*)GlobalLock(hMem);
|
|
memcpy(p, &bi, sizeof(bi));
|
|
|
|
HDC hdc = GetDC(NULL);
|
|
GetDIBits(hdc, captured, 0, bi.biHeight, p + sizeof(bi), (BITMAPINFO*)p, DIB_RGB_COLORS);
|
|
ReleaseDC(NULL, hdc);
|
|
|
|
GlobalUnlock(hMem);
|
|
|
|
if (!SetClipboardData(CF_DIB, hMem)) {
|
|
GlobalFree(hMem);
|
|
}
|
|
}
|
|
CloseClipboard();
|
|
}
|
|
}
|
|
DestroyMenu(menu);
|
|
return 0;
|
|
}
|
|
/*case WM_GETMINMAXINFO: {
|
|
LPMINMAXINFO info = (LPMINMAXINFO) lParam;
|
|
info->ptMaxTrackSize.x = 300;
|
|
info->ptMaxTrackSize.y = 100;
|
|
return 0;
|
|
}*/
|
|
case WM_DESTROY:
|
|
PostQuitMessage(0);
|
|
return 0;
|
|
default:
|
|
return DefWindowProc(hWnd, uMsg, wParam, lParam);
|
|
}
|
|
}
|
|
|
|
LRESULT PreviewWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
|
switch (uMsg) {
|
|
case WM_PAINT: {
|
|
PAINTSTRUCT ps;
|
|
HDC hdc = BeginPaint(hWnd, &ps);
|
|
|
|
RECT size;
|
|
GetClientRect(hWnd, &size);
|
|
int width = size.right - size.left;
|
|
int height = size.bottom - size.top;
|
|
|
|
HDC tempDC = CreateCompatibleDC(hdc);
|
|
HBITMAP tempBmp = CreateCompatibleBitmap(hdc, width, height);
|
|
HGDIOBJ oldObj = SelectObject(tempDC, tempBmp);
|
|
|
|
HBRUSH blackBrush = CreateSolidBrush(RGB(0, 0, 0));
|
|
FillRect(tempDC, &ps.rcPaint, blackBrush);
|
|
DeleteBrush(blackBrush);
|
|
|
|
HDC dcSource = CreateCompatibleDC(tempDC);
|
|
HGDIOBJ oldBmp = SelectObject(dcSource, bmpTarget);
|
|
BLENDFUNCTION blend = getBlendFunction(150);
|
|
|
|
AlphaBlend(tempDC, 0, 0, width, height, dcSource, 0, 0, width, height, blend);
|
|
if (dragging) {
|
|
int cx = dragRect.right - dragRect.left;
|
|
int cy = dragRect.bottom - dragRect.top;
|
|
BitBlt(tempDC, dragRect.left, dragRect.top, cx, cy, dcSource, dragRect.left, dragRect.top, SRCCOPY);
|
|
}
|
|
|
|
SelectObject(dcSource, oldBmp);
|
|
DeleteDC(dcSource);
|
|
|
|
//FillRect(hdc, &dragRect, CreateSolidBrush(RGB(255, 0, 0)));
|
|
BitBlt(hdc, 0, 0, width, height, tempDC, 0, 0, SRCCOPY);
|
|
SelectObject(tempDC, oldObj);
|
|
DeleteDC(tempDC);
|
|
DeleteObject(tempBmp);
|
|
|
|
EndPaint(hWnd, &ps);
|
|
return 0;
|
|
}
|
|
case WM_LBUTTONDOWN: {
|
|
int x = LOWORD(lParam);
|
|
int y = HIWORD(lParam);
|
|
|
|
dragging = TRUE;
|
|
dragRect = {};
|
|
dragRect.left = x;
|
|
dragRect.top = y;
|
|
return 0;
|
|
}
|
|
case WM_LBUTTONUP:
|
|
case WM_MOUSEMOVE: {
|
|
if (dragging) {
|
|
if (wParam == MK_LBUTTON) {
|
|
int x = LOWORD(lParam);
|
|
int y = HIWORD(lParam);
|
|
if (dragRect.right != x || dragRect.bottom != y) {
|
|
dragRect.right = x;
|
|
dragRect.bottom = y;
|
|
InvalidateRect(hWnd, NULL, FALSE);
|
|
}
|
|
} else {
|
|
dragging = FALSE;
|
|
SendMessage(hWnd, WM_CLOSE, 0, 0);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
case WM_DESTROY: {
|
|
if (dragRect.left > dragRect.right) {
|
|
int right = dragRect.right;
|
|
dragRect.right = dragRect.left;
|
|
dragRect.left = right;
|
|
}
|
|
if (dragRect.top > dragRect.bottom) {
|
|
int bottom = dragRect.bottom;
|
|
dragRect.bottom = dragRect.top;
|
|
dragRect.top = bottom;
|
|
}
|
|
|
|
int cx = dragRect.right - dragRect.left;
|
|
int cy = dragRect.bottom - dragRect.top;
|
|
|
|
HDC displayDC = GetDC(NULL);
|
|
HDC tempDC = CreateCompatibleDC(displayDC);
|
|
HBITMAP tempBmp = CreateCompatibleBitmap(displayDC, cx, cy);
|
|
HGDIOBJ oldObj = SelectObject(tempDC, tempBmp);
|
|
|
|
HDC sourceDC = CreateCompatibleDC(tempDC);
|
|
HGDIOBJ fullBmp = SelectObject(sourceDC, bmpTarget);
|
|
BitBlt(tempDC, 0, 0, cx, cy, sourceDC, dragRect.left, dragRect.top, SRCCOPY);
|
|
SelectObject(sourceDC, fullBmp);
|
|
DeleteDC(sourceDC);
|
|
|
|
SelectObject(tempDC, oldObj);
|
|
DeleteDC(tempDC);
|
|
ReleaseDC(NULL, displayDC);
|
|
|
|
if (captured != NULL) {
|
|
DeleteObject(captured);
|
|
} else {
|
|
SetWindowPos(createButton, NULL, 0, 0, 50, 20, SWP_NOMOVE | SWP_NOZORDER);
|
|
penButton = CreateWindow("Button", "Stift", WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, 70, 10, 40, 20, mainWindow, NULL, instance, NULL);
|
|
markerButton = CreateWindow("Button", "Marker", WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, 120, 10, 50, 20, mainWindow, NULL, instance, NULL);
|
|
widePenButton = CreateWindow("Button", "Zensierer", WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, 180, 10, 70, 20, mainWindow, NULL, instance, NULL);
|
|
specialButton = CreateWindow("Button", "Diskrepanz", WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, 260, 10, 80, 20, mainWindow, NULL, instance, NULL);
|
|
}
|
|
captured = tempBmp;
|
|
capturedWidth = cx;
|
|
capturedHeight = cy;
|
|
|
|
SetWindowPos(mainWindow, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW);
|
|
PostMessage(mainWindow, WM_UPDATE_SIZE, 0, 0);
|
|
return 0;
|
|
}
|
|
default:
|
|
return DefWindowProc(hWnd, uMsg, wParam, lParam);
|
|
}
|
|
}
|
|
|
|
int main() {
|
|
if (SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE) != S_OK) {
|
|
return 1;
|
|
}
|
|
|
|
instance = GetModuleHandle(NULL);
|
|
WNDCLASS windowClass = {};
|
|
windowClass.lpszClassName = "BSnippingTool";
|
|
windowClass.hInstance = instance;
|
|
windowClass.lpfnWndProc = WindowProc;
|
|
windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
windowClass.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
|
|
if (RegisterClass(&windowClass) == NULL) {
|
|
return 1;
|
|
}
|
|
WNDCLASS previewWindowClass = {};
|
|
previewWindowClass.lpszClassName = "BSnippingToolPreview";
|
|
previewWindowClass.hInstance = instance;
|
|
previewWindowClass.lpfnWndProc = PreviewWindowProc;
|
|
previewWindowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
if (RegisterClass(&previewWindowClass) == NULL) {
|
|
return 1;
|
|
}
|
|
|
|
mainWindow = CreateWindow("BSnippingTool", "Befator Inc. Snipping Tool", WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, instance, NULL);
|
|
if (mainWindow == NULL) {
|
|
return 1;
|
|
}
|
|
|
|
MSG msg;
|
|
while(GetMessage(&msg, NULL, 0, 0)) {
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
}
|