Caret (bzw. bitmap) einfärben
-
wenn ich ein einfaches caret erstellen möchte, rufe ich ja z.b. CreateCaret(hwnd, (HBITMAP) 0, 1, fontsizex) auf.
dies hat zur folge, dass windows ein schwarzes (bzw. bei schwarzem hintergrund ein weißes) caret erstellt, was bei bspw. blauer oder roter schriftfarbe ziemlich hässlich aussieht.
wenn ich das richtig verstanden habe, muss ich also eine bitmap erstellen, die (bezogen auf das obige beispiel) 1 * fontsizex pixel groß ist und diese dann entsprechend einfärben.
leider erschließt sich mir die vorgehensweise mit den unter https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-createcaret verlinkten funktionen nicht so ganz.
die frage lautet also: wie mache ich das jetzt?
-
@Wade1234 sagte in Caret (bzw. bitmap) einfärben:
wenn ich das richtig verstanden habe, muss ich also eine bitmap erstellen, die (bezogen auf das obige beispiel) 1 * fontsizex pixel groß ist und diese dann entsprechend einfärben.
Die Parameter
nWidth
undnHeight
werden ignoriert, wennhBitmap
nicht0
oder1
ist. Die Dimensionen der übergebenen Bitmap werden dann verwendet.Womit hast du Schwierigkeiten? Mit dem Laden einer Bitmap?
-
-
Minibeispiel mit einem Caret aus einer Bitmap:
#include <windows.h> LRESULT WINAPI window_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam) { static HWND edit_control{}; static HBITMAP bitmap; switch (message) { case WM_CREATE: edit_control = CreateWindow(L"EDIT", L"", WS_VISIBLE | WS_CHILD, 0, 0, 0, 0, window, nullptr, nullptr, 0); if (!edit_control) return -1; bitmap = reinterpret_cast<HBITMAP>(LoadImageW(nullptr, L"caret.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION)); if (!bitmap) return -1; return 0; case WM_SIZE: MoveWindow(edit_control, 0, 0, LOWORD(lparam), HIWORD(lparam), TRUE); return 0; case WM_SETFOCUS: SetFocus(edit_control); CreateCaret(edit_control, bitmap, 0, 0); ShowCaret(edit_control); return 0; case WM_KILLFOCUS: DestroyCaret(); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(window, message, wparam, lparam); } int APIENTRY WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int show_state) { WNDCLASSW wc{ sizeof( wc ) }; wc.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW + 1); wc.hCursor = LoadCursor(nullptr, IDC_ARROW); wc.hInstance = instance; wc.lpfnWndProc = window_proc; wc.lpszClassName = L"TestClass"; wc.style = CS_HREDRAW | CS_VREDRAW; if (!RegisterClassW(&wc)) { MessageBox(nullptr, L"RegisterClass() failed :(", L"Error:", MB_ICONEXCLAMATION); return 0; } auto window = CreateWindowW(wc.lpszClassName, L"TestWindow", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, nullptr, nullptr, instance, 0); if (!window) { MessageBox(nullptr, L"CreateWindow() failed :(", L"Error:", MB_ICONEXCLAMATION); return 0; } UpdateWindow(window); ShowWindow(window, show_state); MSG msg; int result; while ((result = GetMessageW(&msg, window, 0, 0)) != 0) { if (result == -1) break; TranslateMessage(&msg); DispatchMessageW(&msg); } return static_cast<int>(msg.wParam); }
Die Farben der Bitmap müssen dazu invertiert werden.
-
@Swordfish sagte in Caret (bzw. bitmap) einfärben:
Womit hast du Schwierigkeiten? Mit dem Laden einer Bitmap?
nein vereinfacht gesagt möchte ich gerne ein caret haben, das der gewählten schriftfarbe (blau, rot, kaninchenpfurzblauviolett) entspricht und irgendwie fehlt mir da der ansatz.
-
Dann musst Du die Bitmap eben im Speicher erzeugen und malen.
CreateBitmap()
ist Dein Freund.
-
und nPlanes bedeutet dann was? und lpBits ist das ein array von COLORREF?
-
Sorry, ich hab' Dich angelogen mit
CreateBitmap()
... mitCreateCompatibleBitmap()
geht es einfacher:{ HDC dc{ GetDC(edit_control) }; TEXTMETRICW tm; GetTextMetrics(dc, &tm); COLORREF background_color{ GetBkColor(dc) }; HDC mem_dc{ CreateCompatibleDC(dc) }; bitmap = CreateCompatibleBitmap(dc, 5, tm.tmHeight); ReleaseDC(edit_control, dc); SelectObject(mem_dc, bitmap); COLORREF caret_color = RGB(0, 0, 0xff); for (int y{}; y < tm.tmHeight; ++y) for (int x{}; x < 5; ++x) if (!y || y + 1 == tm.tmHeight || x == 2) SetPixel(mem_dc, x, y, RGB(0xff - (caret_color & 0xff), 0xff - ((caret_color >> 8) & 0xff), 0xff - ((caret_color >> 16 ) & 0xff))); else SetPixel(mem_dc, x, y, ~background_color); DeleteDC(mem_dc); }
Einzufügen statt Zeilen 13 - 15 in obigem Bleistift.
-
so ich hatte heute mal die zeit, mich damit zu beschäftigen und aus obigem beispiel folgenden code zusammengebaut:
int CreateProgrammingWindowCaret(int caretposx, int caretposy, const SIZE *fontsize, COLORREF textcolor, HWND hwnd) { HWND hcwnd; HDC dc; HDC hmemdc; HBITMAP hbmp; int i; COLORREF z; int y; hcwnd = CreateWindow("EDIT", "", WS_VISIBLE | WS_CHILD, 0, 0, 0, 0, hwnd, 0, 0, 0); dc = GetDC(hcwnd); hmemdc = CreateCompatibleDC(dc); hbmp = CreateCompatibleBitmap(dc, fontsize->cx, fontsize->cy); ReleaseDC(hwnd, dc); SelectObject(hmemdc, hbmp); for (i = 0; i < fontsize->cy; i++) { z = SetPixel(hmemdc, 1, i, 255); y = GetLastError(); } BOOL a = CreateCaret(hwnd, hbmp, 5, 5); int b = GetLastError(); BOOL c = SetCaretPos(caretposx, caretposy); BOOL d = ShowCaret(hwnd); return 0; }
problem: da blinkt nichts. ich kann da jetzt allerdings keine unterschiede feststellen.
edit: wenn ich statt hbmp 0 oder 1 übergebe, funktionierts aber logischerweise.