i need to create edit box in c++ without using mfc.....
only win32
CreateWindow("EDIT", ...);
. You can use CreateWindowEx
if you prefer, but it's not necessary. To use it, you'll also normally want to have your window respond to WM_FOCUS
by calling SetFocus
to set the focus on the edit control. You'll typically also want to respond to WM_MOVE
(or is it WM_SIZE
- I can't remember) by resizing the edit control to fit the client area of the parent window.
Of course you can also create a dialog ( DialogBox
or DialogBoxEx
) containing an edit control. This avoids having to manually set the focus and such.
So, here's a simple demo program. This creates a main window, and fills its client area with an edit control. It can open and save files, do cut/copy/paste of the data in the control, and select a font in which to display the data in the control. It has an accelerator table, so it knows about the usual keyboard shortcuts for most of those (eg, ctrl-x = cut, ctrl-c = copy, ctrl-v = paste).
First, the main source code:
// 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 *>(¤t), 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;
}
The, the header:
// 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";
Note: the header includes defines for a few commands (find/find-next/replace) that aren't implemented in the program.
Then you need a resource file, on this general order:
// 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
Although not strictly necessary, a Makefile to build it comes in handy:
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
So, if you save those into a directory, open a command prompt for Microsoft's compiler, and type nmake
in that directory, it should build a notepad.exe
, which will be a mildly stripped down version of the normal Windows notepad. It's missing find/replace, printing, and a couple of other things, but at least has enough to give a decent starting point for how to create and use an edit control.
Oh--one other note. This is mostly quickly hacked together from bits and pieces of old code, with a little bit of new duct tape (so to speak) to hold them together. It is not, by any means, exemplary of the best possible coding practices throughout (to put it nicely).
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;
}
Just a small function I use for creating default, blank text boxes.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.