Если я попытаюсь вызвать BeginPaint в WM_PAINT моего подкласса управления расширенным редактированием, он сломается - PullRequest
0 голосов
/ 31 октября 2019

Итак, я сделал подкласс моего элемента управления 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 работать должным образом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...