c++ – The function of saving a file and passing parameters to it

Question:

I am trying to write a regular С++ program with WinApi that will save the text from the editbox to a text file. In order to shorten the code in the DlgProc function, I want to DlgProc function of saving the file into a separate function, so that the button just DlgProc name of the function. Interested in the following, what parameters of the function to transfer to it? I have attached the code of the program itself.

#include <Windows.h>
#include <iostream>
#include "resource.h"

using namespace std;

#define ESC_OF "Отказ от выбора или ошибка выполнения функции "


HWND hEdit2;


CHAR text[] = { 0 };

BOOL CALLBACK DlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, LPSTR lpCmdLine,
int nCmdShow)
{
    DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), 0, (DlgProc), 0);
    return 0;
}

BOOL CALLBACK DlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{

    BOOL success;
    static OPENFILENAME ofn;
    static char szFile[MAX_PATH];


    switch (uMsg) {
    case WM_INITDIALOG: { // Добавление компонентов на форму


                      // Инициализация структуры ofn

    ofn.lStructSize = sizeof(OPENFILENAME);
    ofn.hwndOwner = hwnd;
    ofn.lpstrFile = szFile;
    ofn.nMaxFile = sizeof(szFile);
    ofn.lpstrFilter = "Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0";
    ofn.lpstrDefExt = "txt";


    //Иконка
    HICON hIcon1 = LoadIcon(GetModuleHandle(NULL),
        MAKEINTRESOURCE(IDI_ICON1));
    SendMessage(hwnd, WM_SETICON, 1, (LPARAM)hIcon1);
    //Текстовые поля
    hEdit2 = GetDlgItem(hwnd, IDC_EDIT2);
    SetWindowText(hEdit2, text);
    SetFocus(hEdit2);
    break;
    return TRUE;
} 
case WM_COMMAND:// Обработка кнопок и нажатий
    switch (LOWORD(wParam)) 
    {
    case IDC_SAVE:
        strcpy_s(szFile, "");
        success = GetSaveFileName(&ofn);

        if (success) {
            MessageBox(hwnd, ofn.lpstrFile,
                "Файл сохранен под именем:", MB_OK);
            HANDLE hFile = CreateFile(ofn.lpstrFile,
                GENERIC_WRITE,
                FILE_SHARE_WRITE,
                NULL,
                CREATE_ALWAYS,
                FILE_ATTRIBUTE_NORMAL,
                NULL);
            const int size = 2048;
            TCHAR buff[size] = { 0 };
            hEdit2 = GetDlgItem(hwnd, IDC_EDIT2);
            DWORD off = 0;

            do {
                GetWindowText(hEdit2, buff, size);
                WriteFile(hFile, buff, size, &off, NULL);
            } while (off < 0);

            CloseHandle(hFile);
        }
        else {
            MessageBox(hwnd, ESC_OF"GetSaveFileName",
                "Отказ от выбора или ошибка", MB_ICONWARNING);
        }

        break;

    case IDOK:
        MessageBox(hwnd, "Была нажата кнопка ОК", "Info",
            MB_OK | MB_ICONINFORMATION);
        break;

    case IDCANCEL:
        EndDialog(hwnd, 0);
        return FALSE;
    }

    break;

case WM_CLOSE:
    EndDialog(hwnd, 0);
    return FALSE;
}

return FALSE;
}

Answer:

If a file was created and written in one piece of data at once, then you could simply create a function into which you can pass, for example, a file name plus data for writing, then it would be a function to create a file with a given name and data. It would also be possible, if you want to call the dialog for getting the file name from this function, then you would have to pass to the function not the file name, but, for example, a message for the dialog title, then this would be a function for creating an arbitrary file selected by the user with the specified data. But since I see that the file in the example is written piece by piece, which means that one function is not enough (of course, you can store the context in a global variable in the C style), since a context is needed for writing one file, then it would be possible to create a class that, when created in the constructor, would receive either the file name, or if we want to embed the dialog in the class, then instead of the file name there would be a dialog title, and the class handle would be opened in the destructor via CreateFile, plus the class would have an additional method of type void write(uint8_t const * data, u32 size) for writing the next piece, and the file handle would be stored by a class member, in the destructor you need to close the file handle through CloseHandle.

class FileWriter {
public:
    FileWriter(std::string const & dialog_message) {
        ...
        ofn.lpstrTitle = dialog_message.c_str();
        GetSaveFileName(&ofn);
        hFile_ = CreateFile(ofn.lpstrFile ...);
    }

    ~FileWriter() { CloseHandle(hFile); }

    void Write(uint8_t const * data, uint32_t size) {
        WriteFile(hFile_, data, size, 0, 0);
    }
private:
    HANDLE hFile_;
};
Scroll to Top
AllEscort