在c ++中创建编辑框的最简单方法是什么

时间:2010-09-22 21:54:53

标签: c++ visual-c++ winapi textarea

我需要在不使用mfc的情况下用c ++创建编辑框 只有win32

2 个答案:

答案 0 :(得分:2)

CreateWindow("EDIT", ...);。如果您愿意,可以使用CreateWindowEx,但这不是必需的。要使用它,您通常还希望通过调用WM_FOCUS让您的窗口响应SetFocus来将焦点设置在编辑控件上。您通常还希望通过调整编辑控件的大小来适应父窗口的客户区域来回复WM_MOVE(或者是WM_SIZE - 我记不清了)。

当然,您还可以创建包含编辑控件的对话框(DialogBoxDialogBoxEx)。这避免了必须手动设置焦点等。

所以,这是一个简单的演示程序。这将创建一个主窗口,并使用编辑控件填充其客户区。它可以打开和保存文件,在控件中剪切/复制/粘贴数据,并选择在控件中显示数据的字体。它有一个加速器表,所以它知道大多数通常的键盘快捷键(例如,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 :(得分:1)

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;
}

我用来创建默认空白文本框的小函数。