Какой самый простой способ создать окно редактирования в C ++ - PullRequest
0 голосов
/ 23 сентября 2010

Мне нужно создать поле редактирования в C ++ без использования MFC .....
только win32

Ответы [ 2 ]

2 голосов
/ 23 сентября 2010

CreateWindow("EDIT", ...);. Вы можете использовать CreateWindowEx, если хотите, но это не обязательно. Чтобы использовать его, вы также обычно хотите, чтобы ваше окно отвечало на WM_FOCUS, вызывая SetFocus, чтобы установить фокус на элементе управления редактированием. Как правило, вы также хотите ответить на WM_MOVE (или это WM_SIZE - я не помню), изменив размер элемента управления для редактирования, чтобы он соответствовал клиентской области родительского окна.

Конечно, вы также можете создать диалог (DialogBox или DialogBoxEx), содержащий элемент управления для редактирования. Это позволяет избежать необходимости вручную устанавливать фокус и т. Д.

Итак, вот простая демонстрационная программа. Это создает главное окно и заполняет его клиентскую область элементом управления редактирования. Он может открывать и сохранять файлы, выполнять вырезание / копирование / вставку данных в элементе управления и выбирать шрифт для отображения данных в элементе управления. У него есть таблица ускорителей, поэтому он знает об обычных сочетаниях клавиш для большинства из них (например, ctrl-x = cut, ctrl-c = copy, ctrl-v = paste).

Во-первых, основной исходный код:

// notepad.cpp
#include <windows.h>
#include "notepad.h"
#include <string.h>
#include <string>
#include <fstream>
#include <sstream>

HINSTANCE hInst;
HWND    hwnd;

static const HMENU edit_id = HMENU(100);
static HWND hwndEdit;

void Invalidate(HWND window) {
    RECT rect;
    GetClientRect(window, &rect);
    InvalidateRect(window, &rect, TRUE);
}

class file {
    std::string filename;
    char buffer[FILENAME_MAX];

    void write_file() {
        size_t size = SendMessage(hwndEdit, WM_GETTEXTLENGTH, 0, 0);
        std::string buffer(size+1, '\0');
        SendMessage(hwndEdit, WM_GETTEXT, size + 1, (LPARAM)&buffer[0]);
        std::ofstream out(filename);
        out.write(&buffer[0], size);
    }

    long long get_size(std::string const& filename) {
        WIN32_FIND_DATA data;
        auto h = FindFirstFile(filename.c_str(), &data);
        long long size = data.nFileSizeHigh;
        size <<= 32;
        size |= data.nFileSizeLow;
        return size;
    }

    void read_file() {
        std::ifstream in(filename);
        std::string buffer;
        long long size = get_size(filename);
        if (size > 1024 * 1024) {
            MessageBox(hwnd, "File too large", "", MB_OK);
            return;
        }
        buffer.resize(size+1);
        in.read(&buffer[0], size);
        std::string::size_type pos = 0;
        unsigned count = 0;
        while ((pos = buffer.find('\n', pos)) != std::string::npos) {
            buffer.replace(pos, 1, "\r\n");
            pos += 2;
            ++count;
        }
        SendMessage(hwndEdit, WM_SETTEXT, 0, (LPARAM)buffer.c_str());
    }

public:
    file() : buffer("\0\0") {}
    bool open() {
        if (SendMessage(hwndEdit, EM_GETMODIFY, 0, 0)) {
            if (MessageBox(hwnd, "Open without saving current text?", "Buffer Modified", MB_OKCANCEL) == IDCANCEL)
                return false;
        }
        OPENFILENAMEA spec{};
        spec.lStructSize = sizeof(spec);
        spec.hwndOwner = hwnd;
        spec.lpstrFile = buffer;
        spec.nMaxFile = sizeof(buffer);
        spec.Flags = OFN_ENABLESIZING | OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_SHAREAWARE | OFN_FILEMUSTEXIST;

        if (GetOpenFileName(&spec)) {
            filename = spec.lpstrFile;
            read_file();
            return true;
        }
        return false;
    }

    bool save() {
        if (filename.empty())
            return save_as();
        write_file();
        SendMessage(hwndEdit, EM_SETMODIFY, 0, 0);
        return true;
    }

    bool save_as() {
        OPENFILENAMEA spec{};
        spec.lStructSize = sizeof(spec);
        spec.hwndOwner = hwnd;
        spec.lpstrFile = buffer;
        spec.nMaxFile = sizeof(buffer);
        spec.Flags = OFN_OVERWRITEPROMPT | OFN_ENABLESIZING | OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_SHAREAWARE;

        if (GetSaveFileName(&spec)) {
            filename = spec.lpstrFile;
            write_file();
            SendMessage(hwndEdit, EM_SETMODIFY, 0, 0);
            return true;
        }
        return false;
    }
} file;

class font {
    HFONT current;
    LOGFONT log_font;
    CHOOSEFONT spec;

    bool choose() {
        spec.lStructSize = sizeof(spec);
        spec.hwndOwner = hwnd;
        spec.lpLogFont = &log_font;
        spec.Flags = CF_INITTOLOGFONTSTRUCT | CF_FORCEFONTEXIST | CF_SCREENFONTS;
        return ChooseFont(&spec);
    }
public:
    font()
        : current(NULL)
        , log_font{}
        , spec{}
    {}

    bool select() {
        if (!choose())
            return false;
        current = CreateFontIndirect(&log_font);
        SendMessage(hwndEdit, WM_SETFONT, *reinterpret_cast<WPARAM *>(&current), TRUE);
        return true;
    }
} font;

LRESULT CALLBACK MainWndProc(HWND hwnd,
                             UINT message,
                             WPARAM wparam,
                             LPARAM lparam)
{
    PAINTSTRUCT ps;
    HDC dc;
    RECT rect;
    int i;

    switch (message) {
        case WM_PAINT:
            dc = BeginPaint(hwnd, &ps);
            EndPaint(hwnd, &ps);
            return 0;

        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;

        case WM_CREATE:
            hwndEdit = CreateWindowEx(
                0, 
                "EDIT",
                NULL,
                WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL | ES_WANTRETURN,
                0, 0, 0, 0,
                hwnd,
                edit_id,
                hInst,
                NULL);
            if (hwndEdit == nullptr)
                return -1;
            return 0;

        case WM_SIZE: {
            int width = LOWORD(lparam);
            int height = HIWORD(lparam);

            MoveWindow(hwndEdit, 0, 0, width, height, TRUE);
            break;
        }

        case WM_SETFOCUS:
            SetFocus(hwndEdit);
            break;

        case WM_COMMAND :
            switch(LOWORD(wparam)) {
                case ID_EXIT:
                    if (wparam == ID_EXIT)
                        PostMessage(hwnd, WM_DESTROY, 0, 0);
                    break;
                case ID_FILE_OPEN:
                    if (file.open())
                        return 0;
                    break;
                case ID_FILE_SAVE:
                    if (file.save())
                        return 0;
                    break;
                case ID_FILE_SAVEAS:
                    if (file.save_as())
                        return 0;
                    break;
                case ID_EDIT_UNDO:
                    if (SendMessage(hwndEdit, EM_CANUNDO, 0, 0))
                        SendMessage(hwndEdit, WM_UNDO, 0, 0);
                    return 0;
                case ID_EDIT_SELECT_ALL:
                    SendMessage(hwndEdit, EM_SETSEL, 0, -1);
                    return 0;               
                case ID_EDIT_CUT:
                    SendMessage(hwndEdit, WM_CUT, 0, 0);
                    break;
                case ID_EDIT_COPY:
                    SendMessage(hwndEdit, WM_COPY, 0, 0);
                    break;
                case ID_EDIT_PASTE:
                    SendMessage(hwndEdit, WM_PASTE, 0, 0);
                    break;
                case ID_VIEW_FONT:
                    return font.select();
                default: {
                    return DefWindowProc(hwnd, message, wparam, lparam);
                }
            }
    }
    return DefWindowProc(hwnd, message, wparam, lparam);
}

BOOL Init(HINSTANCE hInstance, int nCmdShow)
{
    WNDCLASSEX wc;


    hInst = hInstance; 

    wc.cbSize        = sizeof(WNDCLASSEX);
    wc.hIconSm       = (HICON)LoadImage(hInstance, 
                                 MAKEINTRESOURCE(IDI_APPICON),
                                 IMAGE_ICON,
                                 16, 16,
                                 0);
    wc.style         = CS_HREDRAW | CS_VREDRAW; 

    wc.lpfnWndProc   = (WNDPROC)MainWndProc;    
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = hInstance;
    wc.hIcon         = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPICON));
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszMenuName  = "MAINMENU";
    wc.lpszClassName = title;

    if (!RegisterClassEx(&wc))
           return FALSE;

    hwnd = CreateWindow(title, 
                        title, 
                        WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
                        CW_USEDEFAULT, 0,
                        CW_USEDEFAULT, 0,
                        NULL,
                        NULL,
                        hInstance,
                        NULL);  

    if (!hwnd) {
        return FALSE;
    }
    ShowWindow(hwnd, SW_SHOWNORMAL);
    UpdateWindow(hwnd);

    return TRUE;
}

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance, 
                     LPSTR     lpCmdLine, 
                     int       nCmdShow)
{
    MSG msg;
    HACCEL AccelTable;

    if (!Init(hInstance, nCmdShow))
        return FALSE;

    AccelTable = LoadAccelerators(hInstance, "SHORTCUTS");

    while (GetMessage(&msg, NULL, 0, 0))
        if (!TranslateAccelerator(hwnd, AccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg); 
        }
    return msg.wParam;
}

Заголовок:

// notepad.h
#define ID_EXIT                             100
#define ID_FILE_OPEN                        101
#define ID_FILE_SAVE                        102
#define ID_FILE_SAVEAS                      103

#define ID_EDIT_CUT                         201
#define ID_EDIT_COPY                        202
#define ID_EDIT_PASTE                       203
#define ID_EDIT_UNDO                        204
#define ID_EDIT_FIND                        211
#define ID_EDIT_FIND_NEXT                   212
#define ID_EDIT_REPLACE                     213
#define ID_EDIT_SELECT_ALL                  214

#define ID_VIEW_WRAP                        301
#define ID_VIEW_FONT                        302

#define IDI_APPICON                         400

static char title[]     = "Minimum Window";

Примечание: заголовок включает определения для нескольких команд (find / find-next / replace), которые не реализованы в программе.

Тогда вам нужен файл ресурса в следующем порядке:

// notepad.rc
#include "notepad.h"

MAINMENU MENU
BEGIN
    POPUP "&File"
    BEGIN
        MENUITEM "Open\tCtrl+O",                ID_FILE_OPEN
        MENUITEM "Save\tCtrl+S",                ID_FILE_SAVE
        MENUITEM "Save As",                     ID_FILE_SAVEAS
        MENUITEM "E&xit",                       ID_EXIT
    END
    POPUP "&Edit"
    BEGIN
        MENUITEM "Undo\tCtrl+Z",                ID_EDIT_UNDO
        MENUITEM "Cut\tCtrl+X",                 ID_EDIT_CUT
        MENUITEM "Copy\tCtrl+C",                ID_EDIT_COPY
        MENUITEM "Paste\tCtrl+V",               ID_EDIT_PASTE
        MENUITEM SEPARATOR
        MENUITEM "Find...\tCtrl+F",             ID_EDIT_FIND
        MENUITEM "Find Next",                   ID_EDIT_FIND_NEXT
        MENUITEM "Replace...\tCtrl+H",          ID_EDIT_REPLACE
        MENUITEM "Select All\tCtrl+A",          ID_EDIT_SELECT_ALL
    END
    POPUP "Format"
    BEGIN
        MENUITEM "&Font",                       ID_VIEW_FONT
    END
END

SHORTCUTS ACCELERATORS
BEGIN
    "^O",           ID_FILE_OPEN,           ASCII   
    "^S",           ID_FILE_SAVE,           ASCII   
    "^A",           ID_EDIT_SELECT_ALL,     ASCII   
    "^Z",           ID_EDIT_UNDO,           ASCII   
    "^X",           ID_EDIT_CUT,            ASCII   
    "^C",           ID_EDIT_COPY,           ASCII   
    "^V",           ID_EDIT_PASTE,          ASCII   
END

Хотя это и не обязательно, Makefile для его сборки пригодится:

notepad.exe: notepad.obj notepad.res
    link notepad.obj user32.lib gdi32.lib comdlg32.lib notepad.res

notepad.res: notepad.rc
    rc -r notepad.rc

notepad.obj: notepad.cpp
    cl -c notepad.cpp

clean:
    del *.res
    del *.obj

Итак, если вы сохраните их в каталог, откроете командную строку для компилятора Microsoft и наберите nmake в этом каталоге, он должен создать notepad.exe, который будет слегка урезанной версией обычной Windows блокнот. В нем отсутствует поиск / замена, печать и пара других вещей, но, по крайней мере, этого достаточно, чтобы дать достойную отправную точку для создания и использования элемента управления для редактирования.

О - еще одна нота. В основном это быстро взламывается из кусочков старого кода, с небольшим количеством новой клейкой ленты (так сказать), чтобы связать их вместе. Это ни в коем случае не является примером наилучшей возможной практики кодирования во всем (мягко говоря).

1 голос
/ 23 сентября 2010
HWND CreateTextBox(CONST INT iX, CONST INT iY, CONST UINT uWidth, CONST UINT uHeight, HWND hWnd, CONST UINT uId, HINSTANCE hInstance)
{
   HWND hWndRet = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("Edit"), NULL, WS_CHILD, iX, iY, (signed)uWidth, (signed)uHeight, hWnd, (HMENU)uId, hInstance, NULL);
   SetBkColor(GetDC(hWndRet), RGB(255, 255, 255));
   return hWndRet;
}

Просто небольшая функция, которую я использую для создания пустых текстовых полей по умолчанию.

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