commit 96979a6299c566502793e1725bf44cd154bfaa71 Author: Bommels05 <69975756+Bommels05@users.noreply.github.com> Date: Fri Jul 10 14:13:18 2026 +0200 Initial Commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..de08f6d --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.idea +cmake-build-* \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..7aedffe --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required(VERSION 4.1) +project(BSnippingTool) + +set(CMAKE_CXX_STANDARD 20) + +add_executable(BSnippingTool main.cpp) + +target_link_libraries(BSnippingTool -static -mwindows) + +target_link_libraries(${CMAKE_PROJECT_NAME} Msimg32) +target_link_libraries(${CMAKE_PROJECT_NAME} Gdiplus) diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..59ac9b9 --- /dev/null +++ b/main.cpp @@ -0,0 +1,747 @@ +#include +#include +#include +#include +#include + +#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 currentMarkings = std::vector(); +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() { + 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); + } +}