Search code examples
c++winapirichedit

"expected nqualified-id before string constant" in RichEdit program


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


Solution

  • 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.