Итак, я сделал подкласс моего элемента управления rich edit и теперь я хочу вставить растровое изображение.
Я установил поле;все отлично работает;Я устанавливаю цвет текста, цвет bkg и шрифт;все отлично работает;Я перехватываю окно моего родителя WM_PAINT
msg и рисую растровое изображение рядом с REC;все отлично работает;Я перемещаю код в подкласс REC (перехват WM_PAINT
, dra ...);все ломается.
REC становится белым, и если я пытаюсь что-то набрать, я получаю черные вертикальные линии (линии курсора - если это так называется), но с другой стороны:image.
После того, как я поработал с кодом WM_PAINT
msg, я пришел к выводу, что если я даже позвоню BeginPaint(hwnd, &ps)
(с EndPaint(hwnd, &ps)
, ofc), он тормозит REC.
Вот код:
//edit_proc :: WM_PAINT
{
PAINTSTRUCT ps;
HDC hdc;
BITMAP bitmap;
HDC hdcMem;
HGDIOBJ oldBitmap;
hdc = BeginPaint(hwnd, &ps);
if (hdc == NULL) __debugbreak();
hdcMem = CreateCompatibleDC(hdc);
oldBitmap = SelectObject(hdcMem, hBitmap);
GetObject(hBitmap, sizeof(bitmap), &bitmap);
BitBlt(hdc, 0, 0, bitmap.bmWidth, bitmap.bmHeight, hdcMem, 0, 0, SRCCOPY);
SelectObject(hdcMem, oldBitmap);
DeleteDC(hdcMem);
EndPaint(hwnd, &ps);
}
break;
РЕДАКТИРОВАТЬ: У меня #define EDIT_CLASS RICHEDIT_CLASS
поверх файла
//WindowProc :: WM_CREATE
{
hBitmap = (HBITMAP)LoadImage(GetModuleHandle(NULL), L"c:\\test.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
LoadLibrary(L"Riched20.dll");
hedit = CreateWindowEx(0, EDIT_CLASS, NULL,
WS_CHILD | WS_VISIBLE | ES_MULTILINE
| ES_AUTOVSCROLL | ES_AUTOHSCROLL | WS_HSCROLL,
0, 0, 100, 100,
hwnd, NULL, GetModuleHandle(NULL), NULL);
if (hedit == NULL)
mb_err("Could not create edit control.");
else {
SendMessage(hedit, EM_SETBKGNDCOLOR, 0, RGB(40, 40, 40));
CHARFORMAT2 format;
memset(&format, 0, sizeof format);
format.cbSize = sizeof(CHARFORMAT2);
format.dwMask = CFM_COLOR | CFM_FACE;
format.crTextColor = RGB(255, 0, 255);
memcpy(format.szFaceName, L"Consolas", sizeof(L"Consolas"));
if (SendMessage(hedit, EM_SETCHARFORMAT, SCF_DEFAULT, (LPARAM)&format) == 0) {
mb_err("Failed to set font.");
}
if (main_edit_proc != NULL)
SetWindowSubclass(hedit, main_edit_proc, 1, 1);
if (SendMessage(hedit, EM_SETTEXTMODE, TM_PLAINTEXT, 0) != 0) {
mb_err("EM_SETTEXTMODE returned non-zero value");
}
//did not set the yHeight, so need to get it (from default)
SendMessage(hedit, EM_GETCHARFORMAT, NULL, (LPARAM)&format);
RECT rect;
SendMessage(hedit, EM_GETRECT, 0, (LPARAM)&rect);
rect.left = format.yHeight / 4;
SendMessage(hedit, EM_SETRECT, 0, (LPARAM)&rect);
}
}
break;
//on the end of the function, I "return DefSubclassProc(hwnd, uMsg, wParam, lParam);"
Я имею в виду ... Я буквально копировать-вставитьWM_PAINT
с edit_proc
на WindowProc
(и изменение второго параметра BitBlt
с 0 на 200), и это работает.
Я посмотрел в интернете, но не нашелвещь об этом. Многие (если не все) результаты поиска используют что-то вроде MFC, но я не хочу сейчас переходить к нему.
Результат моего кода (сначала с WM_PAINT
в WindowProc
, а во-вторых в main_edit_proc
)
Весь код:
#pragma comment(lib, "comctl32.lib")
#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
#include <Richedit.h>
#include <commctrl.h>
#define EDIT_CLASS RICHEDIT_CLASS
#define mb_err(x) MessageBox(NULL, TEXT(x), TEXT("Error!"), MB_ICONEXCLAMATION | MB_OK)
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK main_edit_proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);
HWND hedit = NULL;
HBITMAP hBitmap = NULL;
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow) {
// Register the window class.
const wchar_t CLASS_NAME[] = L"Sample Window Class";
{
WNDCLASSEX wc = { };
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = CLASS_NAME;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if (!RegisterClassEx(&wc)) {
MessageBox(NULL, L"Window Registration Failed!", L"Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
}
// Create the window.
HWND hwnd = CreateWindowEx(
0, // Optional window styles.
CLASS_NAME, // Window class
L"Learn to Program Windows", // Window text
WS_OVERLAPPEDWINDOW, // Window style
// Size and position
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, // Parent window
NULL, // Menu
hInstance, // Instance handle
NULL // Additional application data
);
if (hwnd == NULL) {
MessageBox(NULL, L"Window Creation Failed!", L"Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nCmdShow);
// Run the message loop.
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0) > 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.message;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_CREATE:
{
hBitmap = (HBITMAP)LoadImage(GetModuleHandle(NULL), L"c:\\test.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
LoadLibrary(L"Riched20.dll");
hedit = CreateWindowEx(0, EDIT_CLASS, NULL,
WS_CHILD | WS_VISIBLE | ES_MULTILINE
| ES_AUTOVSCROLL | ES_AUTOHSCROLL | WS_HSCROLL,
0, 0, 100, 100,
hwnd, NULL, GetModuleHandle(NULL), NULL);
if (hedit == NULL)
mb_err("Could not create edit control.");
else {
SendMessage(hedit, EM_SETBKGNDCOLOR, 0, RGB(40, 40, 40));
CHARFORMAT2 format;
memset(&format, 0, sizeof format);
format.cbSize = sizeof(CHARFORMAT2);
format.dwMask = CFM_COLOR | CFM_FACE;
format.crTextColor = RGB(255, 0, 255);
memcpy(format.szFaceName, L"Consolas", sizeof(L"Consolas"));
if (SendMessage(hedit, EM_SETCHARFORMAT, SCF_DEFAULT, (LPARAM)&format) == 0) {
mb_err("Failed to set font.");
}
if (main_edit_proc != NULL)
SetWindowSubclass(hedit, main_edit_proc, 1, 1);
if (SendMessage(hedit, EM_SETTEXTMODE, TM_PLAINTEXT, 0) != 0) {
mb_err("EM_SETTEXTMODE returned non-zero value");
}
//did not set the yHeight, so need to get it (from default)
SendMessage(hedit, EM_GETCHARFORMAT, NULL, (LPARAM)&format);
RECT rect;
SendMessage(hedit, EM_GETRECT, 0, (LPARAM)&rect);
rect.left = format.yHeight / 4;
SendMessage(hedit, EM_SETRECT, 0, (LPARAM)&rect);
}
break;
}
/* end the program */
case WM_DESTROY:
DeleteObject(hBitmap);
PostQuitMessage(0);
return 0;
case WM_CLOSE:
//KillTimer(hwnd, timer0_id);
DestroyWindow(hwnd);
return 0;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
LRESULT CALLBACK main_edit_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) {
switch (uMsg) {
case WM_CREATE:
break;
case WM_SETCURSOR:
{
POINT pos;
GetCursorPos(&pos);
HWND cur_hwnd = WindowFromPoint(pos);
if (cur_hwnd == hwnd) SetCursor(LoadCursor(NULL, IDC_ARROW));
else SendMessage(cur_hwnd, WM_SETCURSOR, 0, 0);
return 0;
}
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc;
BITMAP bitmap;
HDC hdcMem;
HGDIOBJ oldBitmap;
hdc = BeginPaint(hwnd, &ps);
if (hdc == NULL) __debugbreak();
hdcMem = CreateCompatibleDC(hdc);
oldBitmap = SelectObject(hdcMem, hBitmap);
GetObject(hBitmap, sizeof(bitmap), &bitmap);
BitBlt(hdc, 0, 0, bitmap.bmWidth, bitmap.bmHeight, hdcMem, 0, 0, SRCCOPY);
SelectObject(hdcMem, oldBitmap);
DeleteDC(hdcMem);
EndPaint(hwnd, &ps);
break;
}
}
return DefSubclassProc(hwnd, uMsg, wParam, lParam);
}
РЕДАКТИРОВАТЬ: Я пытаюсь сделать это . Но я даже не могу заставить BeginPaint работать должным образом.