질문과 답변

윈도우즈 API완전정복 1권 974p 질문있습니다. 날짜:2024-9-19 10:07:30 조회수:788
작성자 : 황금가물치
포인트 : 86
가입일 : 2022-05-06 15:33:18
방문횟수 : 69
글 12개, 댓글 13개
소개 : 안녕하세요. 윈도우즈api를 공부하기위하여 가입했습니다. 잘 부탁드립니다.
작성글 보기
쪽지 보내기
#include "pch.h"
#include "framework.h"
#include "Ex_974p_ReadFile.h"

LPCTSTR MyClassName = TEXT("ReadFile");
HINSTANCE g_hInst{};
HWND hWndMain{};
TCHAR buf[1024]{};

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) {
    HWND hWnd{};
    MSG msg{};
    WNDCLASSEXW wndclassexw{};

    g_hInst = hInstance;

    wndclassexw.lpfnWndProc = WndProc;
    wndclassexw.hInstance = hInstance;
    wndclassexw.lpszClassName = MyClassName;
    wndclassexw.hIconSm = NULL;
    wndclassexw.cbSize = sizeof(WNDCLASSEX);
    wndclassexw.cbClsExtra = 0;
    wndclassexw.cbWndExtra = 0;
    wndclassexw.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclassexw.hIcon = LoadIconW(NULL, IDI_APPLICATION);
    wndclassexw.hCursor = LoadCursorW(NULL, IDC_ARROW);
    wndclassexw.lpszMenuName = NULL;
    wndclassexw.style = CS_VREDRAW | CS_HREDRAW;

    RegisterClassExW(&wndclassexw);

    hWnd = CreateWindowExW(NULL, MyClassName, MyClassName, WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, (HMENU)NULL, hInstance, NULL);

    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);

    while (GetMessageW(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessageW(&msg);
    }
    return((int)msg.wParam);
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) {
    
    HDC hdc{};
    PAINTSTRUCT ps{};
    HANDLE hFile{};
    DWORD dwRead{};
    RECT rt{};

    switch (iMessage) {
    case WM_LBUTTONDOWN:
        hFile = CreateFile(L"Test.txt", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
        if (hFile != INVALID_HANDLE_VALUE) {
            if (ReadFile(hFile, buf, 1024, &dwRead, NULL)) {
                CloseHandle(hFile);
                InvalidateRect(hWnd, NULL, TRUE);
            }
        }
        return(0);
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        GetClientRect(hWnd, &rt);
        DrawText(hdc, buf, -1, &rt, DT_WORDBREAK);
        EndPaint(hWnd, &ps);
        return(0);
    case WM_DESTROY:
        PostQuitMessage(0);
        return(0);
    }
    return(DefWindowProcW(hWnd, iMessage, wParam, lParam));
}


------------------------------------------------------------------------------------------------------------------------------------------
위 예제를 실행할 시 Test.txt파일을 읽어올 시 한글이 깨지는 현상이 나타납니다.
영어로 텍스트 파일을 저장해도 마찬가지로 깨짐니다.
텍스트 파일을 읽어들일 시 깨지지 않게 하기위해 어떻게 해야하는지 궁금합니다.



김민수
error code: 522 error code: 522

목록보기 삭제 수정 신고 스크랩

Program 9월21일 2:49:36  

txt파일은 좀 미묘해서 나도 잘 모릅니다만 나는 그냥 아래코드로 txt파일을 읽어옵니다
      FILE * fp;
    char * buffer;
    long fsize;

    TCHAR imsistr[128];

    fopen_s(&fp , test.txt , "rb");
    if(fp==NULL)
    {
        //MessageBox(L"edu2text0.txt 파일 열기 에러");
    }  
    else
    { 
        // 파일의 크기를 구함 
        fseek(fp, 0L, SEEK_END); //파일포인터를 파일의 끝으로 이동
        fsize = ftell(fp); //현재 파일포인터를 읽으면 파일크기가 됨
        fseek(fp, 0L, SEEK_SET); //파일포인터를 다시 파일의 맨 처음으로 이동
        buffer = (char*)malloc(fsize +1); //파일의 내용을 담을 버퍼를 할당

        fread((void *)buffer,fsize,1,fp);
        fclose(fp); 
        //
        ZeroMemory(imsistr,sizeof(imsistr));
        MultiByteToWideChar(CP_ACP, 0, buffer,-1, imsistr, sizeof(imsistr));//buf 내용을 imsistr 로 바꾼다 (txt파일내용을 TCHAR 로 바꾼다)
        imsistr[128-1]=L'\0';

        free(buffer);
    }
이렇게 준비한 다음 DrawText 출력을 해보세요

    DrawText(hdc,imsistr,-1,&rt,DT_WORDBREAK);//이렇게 출력하면 될려나?

황금가물치 9월21일 3:44:23  

c언어 상 fope함수로는 열립니다.
저는 일단 책에 있는 대로 공부하고 있고 createfile과 readfile함수가 깨져서 다른 방법이 없는지 궁금합니다. 혹시 utf-8이나 ansi설정을 비주얼스튜디오에서 해야하는지 궁금하기도 하고요.
책 예제에 나와있는 것들은 예전 win32로 작성되서 작동이 됩니다.
비주얼스튜디오2022에서는 글씨가 깨지고요. 혹시 다른 방법이 없을지?

Program 9월22일 3:37:41  

case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
GetClientRect(hWnd, &rt);
//DrawText(hdc, buf, -1, &rt, DT_WORDBREAK);//이 라인을 주석처리하고
MultiByteToWideChar(CP_ACP,0,(char *)buf,-1,imsistr, sizeof(imsistr));//이 두라인으로 바꾸어 보세요
DrawText(hdc,imsistr,-1,&rt,DC_WORDBREAK);/////////////////////////////////
EndPaint(hWnd, &ps);
return(0);
결론은 ReadFile로 읽은 buf는 TCHAR 형 이지만 char 형으로 저장되어 있습니다
그래서 char 형을 다시 TCJAR 형으로 바꾼뒤 DrawTExt로 출력합니다
왜 그런지는 나도 잘 모르나 나는 항상 txt파일은 char -> TCHAR 로 바꾸어 출력합니다.
아마 예전에 (유니코드이전에 ANSI 때 ) txt파일 형식을 유지하고 있는 것 같습니다

황금가물치 9월22일 5:19:15  

답변감사합니다.
imsistr는 어떤 변수인지요?
저기서부터 궁금해서요. imsistr라는 변수가 갑자기 나와서 저것도 TCHAR인지요?

황금가물치 9월22일 5:21:33  

imsistr가 TCHAR로 임시로 저장하는 변수군요. 너무 감사합니다.ㅜㅜ
계속해서 책으로 혼자 공부하다보니 모르는게 너무 많아서.
일단 마이크로소프트 쪽에도 질문했는데 먼저 답변해주셔서 감사합니다.
친절한 답변 정말 감사합니다.ㅜㅜ

Program 9월22일 5:26:55  

아 참
TCHAR imsistr[64]; //요것 먼저 선언해 놓고하면 됩니다.
그런데 내가 여러경우를 실험해 본 결과
txt파일이 항상 ASCII 로만 되어 있는 줄 알았는데
MFC에서 CArchive ar;
ar.WriteSTring() 과 ar.ReadString()에서는 굳이 ASCII -> UNICODE 변환해 주지 않아도
곧 바로 TCHAR 변수를 출력하면 깨지지 않고 잘 됩니다.
그래서 이때 WriteString으로 생성한 txt파일을 위 코드에 대입하여 불러와 출력해 보니
예상은 ASCII 코드로 글자가 깨지리라 예상했는데 오히려 이때는 바로 UNICODE 로 되어 잘 출력되고
오히려 MultiByteToWideChar로 변환후 출력하니 정상적인 출력이 안 나옵니다.
즉 항상 txt파일의 포멧이 ASCII로 생각했으나 어떤때는 UNICODE 인것 같기도 하고해서
나도 헷갈립니다. txt파일의 구조가 일관성이 없는건지 내가 잘 모르는 건지 아무튼 txt파일은 txt파일입니다 이상

황금가물치 9월22일 6:00:01  

공부할때 참고하도록 하겠습니다.

Program 9월22일 6:28:14  

계속 궁금해서 호기심을 발동하여 몇가지 더 실험을 해 보았습니다.
일단 fopen("c:\test.txt","wt"); 와
hFile = CreateFile(L"Test.txt", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
에서 차이점을 보면 첫번째 인수가 char * 인가 아니면 TCHAR * 인가에 따라서 ASCII txt파일을 생성하느냐?
아니면 UNICODE txt 파일을 생성하느냐? 이렇게 예상하였는데 이게 아니고
MFC로
CFile file;
file.Open(L".\c:\test.txt",CFile::modeCreate | CFile::modeWrite | CFile::modeNoTruncate);
file.Seek(0,file.end);
file.WriteString(L"Korean");//바로 WriteString()하면 ASCII 코드로 txt파일 생성디고
/////////////////////////////////////////////////////////////////////////////
CArchive ar(&file,CArchive::store);//<==요놈을 정의하고 WriteString()하면
ar.WriteString(L"Korean");//UNICODE로 txt파일 생성되더라
일단 이렇게 까지 실험해 보았음


로그인하셔야 댓글을 달 수 있습니다.