I am trying to load a RichEdit component for my Win32 Application, however when loading the class name I get the following error:
"expected nqualified-id before string constant"
I am only 17 years-old, so please understand this code is probably not going to be the greatest you will see.
I have tried using an older version of RichEdit (Riched20.dll), but this gave the same error. When looking online, other StackOverflow sources have said it can be as simple as a missing semi-colon or an include added a second time. However, I have been looking over this for the past hour, and have yet to see anything. Any help would be greatly appreciated! I also tried compiling with UNICODE because I know string literals can be goofy sometimes. I'm using TDM-GCC to compile, so is there a possibility that the command I am entering is incorrect?
WinMain.cpp
#define UNICODE
#define _UNICODE
#include <windows.h>
#include <commctrl.h>
#include <commdlg.h>
#include <richedit.h>
#include <iostream>
#include <string>
#include <fstream>
#define ID_FILE_OPEN 1
#define ID_FILE_SAVE 2
#define ID_FILE_EXIT 3
const wchar_t CLASS_NAME[] = L"Win32 Text Editor";
static const wchar_t MSFTEDIT_CLASS[] = L"RICHEDIT20W";
// Function prototypes
void LoadFileContents(const std::wstring& filePath, HWND hRichEdit);
void SaveFileContents(const std::wstring& filePath, HWND hRichEdit);
void OpenFile(HWND hwnd);
void SaveFile(HWND hwnd);
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
// Main entry point
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR, int nCmdShow) {
// Load RichEdit DLL
LoadLibrary(L"Riched20.dll");
InitCommonControls();
WNDCLASS wc = {};
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
HWND hwnd = CreateWindowEx(
0, CLASS_NAME, L"Win32 Text Editor", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 800, 600,
nullptr, nullptr, hInstance, nullptr);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
MSG msg = {};
while (GetMessage(&msg, nullptr, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
// Window Procedure
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
static HWND hRichEdit;
switch (uMsg) {
case WM_CREATE:
hRichEdit = CreateWindowEx(
0, MSFTEDIT_CLASS, nullptr, WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL |
ES_MULTILINE | ES_AUTOVSCROLL | WS_BORDER,
0, 0, 800, 600, hwnd, nullptr, ((LPCREATESTRUCT)lParam)->hInstance, nullptr);
break;
case WM_SIZE:
MoveWindow(hRichEdit, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
break;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case ID_FILE_OPEN:
OpenFile(hwnd);
break;
case ID_FILE_SAVE:
SaveFile(hwnd);
break;
case ID_FILE_EXIT:
PostQuitMessage(0);
break;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}
// File handling functions
void OpenFile(HWND hwnd) {
OPENFILENAME ofn = {};
wchar_t szFile[260] = {};
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwnd;
ofn.lpstrFile = szFile;
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = L"Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0";
ofn.lpstrTitle = L"Open a file";
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
if (GetOpenFileName(&ofn)) {
LoadFileContents(ofn.lpstrFile, hwnd);
}
}
void SaveFile(HWND hwnd) {
OPENFILENAME ofn = {};
wchar_t szFile[260] = {};
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwnd;
ofn.lpstrFile = szFile;
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = L"Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0";
ofn.lpstrTitle = L"Save a file";
ofn.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT;
if (GetSaveFileName(&ofn)) {
SaveFileContents(ofn.lpstrFile, hwnd);
}
}
void LoadFileContents(const std::wstring& filePath, HWND hRichEdit) {
std::wifstream file(filePath.c_str());
if (file.is_open()) {
std::wstring content((std::istreambuf_iterator<wchar_t>(file)),
(std::istreambuf_iterator<wchar_t>()));
SetWindowText(hRichEdit, content.c_str());
}
}
void SaveFileContents(const std::wstring& filePath, HWND hRichEdit) {
std::wstring content;
int length = GetWindowTextLength(hRichEdit);
if (length > 0) {
content.resize(length + 1); // Resize for null terminator
GetWindowText(hRichEdit, &content[0], length + 1);
}
std::wofstream file(filePath.c_str());
if (file.is_open()) {
file << content;
}
}
GCC Command
g++ -o TextEditor.exe WinMain.cpp -mwindows -lcomdlg32 -lcomctl32 -lmsftedit
richedit.h
contains this statement:
#define MSFTEDIT_CLASS L"RICHEDIT50W"
This means that the following statement in your code:
static const wchar_t MSFTEDIT_CLASS[] = L"RICHEDIT20W";
is transformed by the preprocessor into this:
static const wchar_t L"RICHEDIT50W"[] = L"RICHEDIT20W";
which is obviously invalid syntax. You can simply remove this line from your code, as the value of MSFTEDIT_CLASS
is provided by the richedit.h
header file for you.