C言語のWindowsプログラミングでのWriteFile関数と改行・文字表示に関する質問

このQ&Aのポイント
  • C言語のWindowsプログラミングで学習中の質問者が、WriteFile関数を使用して文字列を表示し、画面上とファイルに改行を入れる方法に関して質問しています。
  • さらに、保存したファイルを開くと文字と文字の間に半角スペースが入る現象についても質問しています。
  • UNICODEとマルチバイトの関係についても触れられており、UNICODEを定義するとGetSaveFileName関数がエラーになるため、マルチバイトを定義せざるを得ない状況にあるようです。
回答を見る
  • ベストアンサー

WriteFile関数

WriteFile関数 C言語でWindowsプログラミングを学習中です。 2点ご質問です。 LPTSTR型のbufferには(1)のように文字列を格納して、 画面に表示しています。 ファイルに保存するために改行は「\r\n」に置き換えているので、 画面上ではもちろん改行されません。 Editコントロールを使用すれば簡単にいくと思いますが、 このような方法で画面上にも改行・ファイルにも改行という方法はありますか? さらに(2)で保存したファイルを開くと文字と文字の間に半角のスペースが 入ってしまいます。 ごくたまに入らない時もありますが、文字列の一部しか表示されません。 これはUNICODEとマルチバイトの関係なのでしょうか? UNICODEを定義しています。 マルチバイトを定義してしまうとGetSaveFileName関数が エラーになってしまうので・・・ ご教授お願いします。 (1) case WM_CHAR: if(wp==VK_BACK){ if(!iCount) return 0; iCount--; InvalidateRect(hWnd,NULL,TRUE); }else if(wp==VK_RETURN){ buffer[iCount++]='\r\n'; InvalidateRect(hWnd,NULL,TRUE); return 0; }else{ buffer[iCount++]=(TCHAR)wp; InvalidateRect(hWnd,NULL,TRUE); } return 0; case WM_PAINT: hdc=BeginPaint(hWnd,&ps); GetClientRect(hWnd,&rc); DrawText(hdc,buffer,iCount,&rc,DT_WORDBREAK); EndPaint(hWnd,&ps); return 0; ・ ・ ・ ・ (2) int MySave(LPTSTR buffer,HWND hWnd) { OPENFILENAME ofn; HANDLE hFile; TCHAR szFile[MAX_PATH]; TCHAR szFileTitle[MAX_PATH]; DWORD dwAccBytes; memset(&ofn,0,sizeof(OPENFILENAME)); ofn.lStructSize=sizeof(OPENFILENAME); ofn.hwndOwner=hWnd; ofn.lpstrFilter=TEXT("text(*.txt)\0*.txt\0All files(*.*)\0*.*\0\0"); ofn.lpstrFile=szFile; ofn.lpstrFileTitle=szFileTitle; ofn.nFilterIndex=1; ofn.nMaxFile=MAX_PATH; ofn.nMaxFileTitle=MAX_PATH; ofn.Flags=OFN_OVERWRITEPROMPT|OFN_HIDEREADONLY; ofn.lpstrDefExt=TEXT("txt"); ofn.lpstrTitle=TEXT("名前を付けて保存"); if(!GetSaveFileName(&ofn)) return -1; hFile=CreateFile(szFile,GENERIC_WRITE,0,NULL, CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); WriteFile(hFile,buffer,(DWORD)lstrlen(buffer), &dwAccBytes,NULL); SetWindowText(hWnd,szFileTitle); CloseHandle(hFile); return 0; }

質問者が選んだベストアンサー

  • ベストアンサー
  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.1

文字列について、もう少し勉強した方がいいと思いますが……。 case WM_CHAR: でいぢっているbuffer[]には、文字列の終端をあらわす'\0'についての処理は入っていますか? '\0'が入っていないのであれば、 >WriteFile(hFile,buffer,(DWORD)lstrlen(buffer), >&dwAccBytes,NULL); >SetWindowText(hWnd,szFileTitle); の2つはバッファオーバーランする可能性が限りなく高いですが、それは意図した動作ですか? # ついでにhWndは何者ですか?

scanfprintf
質問者

お礼

遅くなり申し訳ございません。 仰っていただいたとおり文字列に関してはもう一度勉強しなおします。 大変参考になりました。 WriteFile(hFile,buffer,(DWORD)lstrlen(buffer)を下記の通りにすると、 解消されました。 WriteFile(hFile,buffer,lstrlen(buffer)*sizeof(TCHAR);

関連するQ&A

  • ファイル名の取得について

    以下のサンプルで、選択したファイル名を任意の変数に取得したいのですが、どこに手を加えると取得できますでしょうか。 void OpenImgFiles(HWND hWnd) {   OPENFILENAME ofn;   memset(&ofn, 0, sizeof(OPENFILENAME));   ofn.lStructSize = sizeof(OPENFILENAME);   ofn.hwndOwner = hWnd;   ofn.lpstrFilter = "BMP files(*.bmp)\0*.bmp\0All Files(*.*)\0*.*\0\0";   ofn.lpstrFile = FileName;   ofn.nMaxFile = MAX_PATH;   ofn.Flags = OFN_FILEMUSTEXIST;   ofn.lpstrDefExt = "bmp";   ofn.nMaxFileTitle = 64;   ofn.lpstrFileTitle = FileTitle;   ofn.lpstrTitle = "ファイルを開く";   if (GetOpenFileName(&ofn)) {     show = 1;     InvalidateRect(hWnd, NULL, TRUE);   }   return; } ひょっとして簡単すぎるのかも知れませんが・・・ どうかよろしくお願いします。

  • bmpファイルビューアを作るため

    猫のサイトのコードを使って void OpenImgFiles(HWND hWnd) { OPENFILENAME ofn; memset(&ofn, 0, sizeof(OPENFILENAME)); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hWnd; ofn.lpstrFilter = "BMP files(*.bmp)\0*.bmp\0All Files(*.*)\0*.*\0\0"; ofn.lpstrFile = FileName; ofn.nMaxFile = MAX_PATH; ofn.Flags = OFN_FILEMUSTEXIST; ofn.lpstrDefExt = "bmp"; ofn.nMaxFileTitle = 64; ofn.lpstrFileTitle = FileTitle; ofn.lpstrTitle = "ファイルを開く!"; if (GetOpenFileName(&ofn)) { show = 1; InvalidateRect(hWnd, NULL, TRUE); } return; } を呼び出してファイルを開くためのダイアログボックスを表示しようとしてのですが無応答で何も表示してくれません コンパイラは無償Borland C++5.5です 何が悪いか教えてください

  • LPTSTR型の変数に文字を格納

    LPTSTR型の変数に文字を格納 現在C言語でWindowsプログラミングを学習しています。 LPTSTR 型の変数にキーボードから入力されて1文字づつ格納したいのですが、 下記のコードであればうまくいきません。 自分がTCHARやLPTSTRのことを根本から理解できていないのが原因だと思うのですが。 LRESULT CALLBACK WndProc(HWND hWnd,UINT msg,WPARAM wp,LPARAM lp) { static LPTSTR buffer; HDC hdc; PAINTSTRUCT ps; switch(msg){ case WM_CHRAR: *buffer++=(TCHAR)wp; InvalidateRect(hWnd,NULL,TRUE); return 0; case WM_PRINT: hdc=BeginPaint(hWnd,&ps); DrawText(hdc,buffer,-1,&rc,DT_WORDBREAK); EndPaint(hWnd,&ps); return 0; ・ ・ ・ ・

  • C言語の自作関数がエラーになる

    C言語の自作関数がエラーになる 現在C言語でWindowsのプログラミングを学習中ですが あるプロトタイプ宣言した自作の関数がエラーになってしまいます。 エラー内容は「未解決の外部シンボル・・・」といった内容です。 関数の引数をHWNDだけにした場合は問題ありませんでした。 環境はMicrosoft Visual C++ 2008 Express Editionです。 自作関数の引数に型の制限はあるのでしょうか? よろしくお願いします。 以下コード一部です LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM); int MySave(TCHAR *,HWND,int); ・ ・ ・ LRESULT CALLBACK WndProc(HWND hWnd,UINT msg,WPARAM wp,LPARAM lp) { THCAR buffer[1024]; int iCount; ・ ・ ・ MySave(buffer,hWnd,iCount); ・ ・ ・ } int MySave(buffer,hWnd,iCount); ・ ・ ・ }

  • WINAPIのスレッドについて教えてください

    WINAPIのスレッドについて教えてください スレッドを作成して写真をスライドショウー的に表示しようしていますが、 上手くいきません。 typedef struct _dataparam{ HWND hWnd; HDC hSlidDC; int iFileCount; TCHAR szFile[100][MAX_PATH]; HBITMAP hBitmap[100]; }DataParam; という構造体を作成して、各変数に必要な値を代入した後 BIT_SLIDというメッセージが来た場合Threadを作成。 LRESULT CALLBACK WndProc(HWND hWnd,UINT msg,WPARAM wp,LPARAM lp) { static DataParam data={0}; case WM_CREATE: data.hWnd=hWnd; ・ ・ case BIT_SLID: slidCheck=TRUE; CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)SlidThread, (LPVOID)&data,0,&dwThreadId); return 0; Thread関数内でGetClientRectにより下記のように Windowのサイズを測ろうとしましたが rcには正しいWindowのサイズ格納されていません。 DWORD WINAPI SlidThread(LPVOID vdParam) { DataParam *SlidData; RECT rc={0}; SlidData=(DataParam *)vdParam; GetClientRect(SlidData->hWnd,&rc); ・ ・ ・ hWnd以外のiFileCountやszFile[100][MAX_PATH]の値を調べると 問題なく引き渡しているようなのですが、 rcのleft=0 light=459 top=760 bottom=-2142242063となっていました。 けれどThread関数内で InvalidateRect(SlidData->hWnd,NULL,TRUE); 再描画を行います。 ちなみに下記の自作関数では問題なくWindowサイズを取得しております。 int MySetBitmap(HDC hNormalDC,DataParam *data) { GetClientRect(data->hWnd,&rc); ・ ・ ・ 環境はMicrosoft Visual C++ 2008 Express Editionです それと別件なのですが、デバックでローカルに表示される変数と 表示されない変数がありますがその違いを教えていただければ幸いです。 今回SlidDataは表示されません。 ご教授お願いします。

  • DragQueryFile()でエラー

    現在、VC++2005SP1でダイアログベースのアプリを書いていますが、エディットコントールでのドラッグアンドドロップの実装で躓いています。なぜかDragQueryFile()で-1が返って来て直後にGetlastError()を呼ぶと6(無効なハンドル)が返って来ます。 現象の再現を確認しながらコードを以下のレベルまで簡略にしました。 どこかまずいところがあればご教示頂きたく思います。 #include "stdafx.h" #include <stdio.h> #include <locale.h> #include <shellapi.h> #include "Resource.h" TCHAR input_file[MAX_PATH]; void InitDialog( HWND hWnd ); LRESULT CALLBACK MyDragDropProc( HWND, unsigned, WORD, LONG ); WNDPROC lpfnOldEditProc; LRESULT CALLBACK DlgProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp); int APIENTRY _tWinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPTSTR lpCmdLine, int nCmdShow ) {   _tsetlocale(LC_ALL, _T(""));   INT_PTR dret = DialogBox(hInst, MAKEINTRESOURCE( IDD_DIALOG ), NULL, (DLGPROC)DlgProc );   return 0; } LRESULT CALLBACK DlgProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) {   switch (msg) {   case WM_INITDIALOG: InitDialog( hWnd ); return TRUE;   case WM_COMMAND:     switch (LOWORD(wp)) {     case IDOK: EndDialog(hWnd, IDOK); return TRUE;     case IDCANCEL: EndDialog(hWnd, IDCANCEL); return TRUE;     }   }   return FALSE; } void InitDialog( HWND hWnd ) {   DragAcceptFiles( GetDlgItem( hWnd, IDC_EDIT_INPUT_FILE ), TRUE );   lpfnOldEditProc = (WNDPROC)SetWindowLong( GetDlgItem( hWnd, IDC_EDIT_INPUT_FILE ), GWL_WNDPROC, (LONG)MyDragDropProc ); } LRESULT CALLBACK MyDragDropProc( HWND hWnd, unsigned msg, WORD wp, LONG lp ) {   UINT wFilesDropped;   HDROP hDrop = (HDROP)wp;   TCHAR buff[256];   int err;   switch ( msg ) {   case WM_DROPFILES:     wFilesDropped = DragQueryFile( hDrop, (UINT)-1, NULL, 0 );     err = GetLastError();     _itot_s( err, buff, 256, 10 );     MessageBox( NULL, buff, NULL, MB_OK );     wFilesDropped = DragQueryFile( (HDROP)wp, 0, input_file, MAX_PATH );     MessageBox( hWnd, input_file, NULL, MB_OK );     DragFinish( hDrop );     break;   default:     return CallWindowProc( (WNDPROC)lpfnOldEditProc, hWnd, msg, wp, lp );   }   return 0; }

  • 猫でもわかるプログラミング74章

    74章は http://www.kumei.ne.jp/c_lang/sdk/sdk_74.htm です。簡単なメモ帳をつくるというお題で、その中に ファイルをオープンするとき、 char szFileName[256];// オープンするファイル名(パス付き) char szFile[64];// ファイル名 OPENFILENAME ofn; として、 … ofn.lpstrFile = szFileName; //フルパスつきファイル名を格納 ofn.lpstrFileTitle = szFile;//選択されたファイル名が格納されます … GetOpenFileName関数 として、「ファイルを開く」のコモンダイアログを開いてファイル名等等を取得し、 CreateFileでそのファイルをopenするという例題なのですが、 szFileNameにはパスつきファイル名が格納されているのですが、szFileにはなにも格納されていないみたいなんです。ずっと色々悩んでいるのですが、どこがいけないでしょうか。 VC++ 6.0 WinXP

  • Win32API ファイルの書き込み、保存

    Win32APIを使って、ファイルの保存ダイアログを表示→ファイルを指定→保存ボタンを押す→指定されたファイルに書き込む→指定したファイルを保存 というプログラムを作りたいと考えています。しかし、ファイルに書き込んだ後どう保存すればいいかわからないので教えてください。s[256]をfilename_fullに書き込んで保存したいです。この場合プログラムは抜粋したものなので、s[256]に文字が格納してあると考えてください。 char s[256]; FILE *fp; static OPENFILENAME ofn; static TCHAR filename_full[MAX_PATH]; // ファイル名(フルパス)を受け取る領域 static TCHAR filename[MAX_PATH]; // ファイル名を受け取る領域 // 構造体に情報をセット ZeroMemory( &ofn, sizeof(ofn) ); // 最初にゼロクリアしておく ofn.lStructSize = sizeof(ofn); // 構造体のサイズ ofn.hwndOwner = hWnd; // コモンダイアログの親ウィンドウハンドル ofn.lpstrFilter = _T("text(*.txt)\0*.txt\0All files(*.*)\0*.*\0\0"); // ファイルの種類 ofn.lpstrFile = filename_full; // 選択されたファイル名(フルパス)を受け取る変数のアドレス ofn.lpstrFileTitle = filename; // 選択されたファイル名を受け取る変数のアドレス ofn.nMaxFile = sizeof(filename_full); // lpstrFileに指定した変数のサイズ ofn.nMaxFileTitle = sizeof(filename); // lpstrFileTitleに指定した変数のサイズ ofn.Flags = OFN_OVERWRITEPROMPT; // フラグ指定 ofn.lpstrTitle = _T("名前を付けて保存");// コモンダイアログのキャプション ofn.lpstrDefExt = _T("txt"); // デフォルトのファイルの種類 // 名前を付けて保存コモンダイアログを作成 if( !GetSaveFileName( &ofn ) ) { MessageBox( hWnd, _T("エラー"), _T("エラー"), MB_OK ); SendMessage( hWnd, WM_CLOSE, 0, 0 ); }else{ if((fp=fopen(filename_full,"w")) == NULL) { MessageBox( hWnd, _T("エラー"), _T("エラー"), MB_OK ); SendMessage( hWnd, WM_CLOSE, 0, 0 ); exit(0); /* (3)エラーの場合は通常、異常終了する */ } /*ここからがわかりません*/     /*s[256]をファイルに書き込んで、保存するプログラムを教えてください。

  • ファイルの保存ダイアログでデフォルト命名したい

    ファイルの保存ダイアログでデフォルト命名したい Win32API(C言語)編 第55章 ファイルを開く・保存のコモンダイアログ http://www.geocities.jp/ky_webid/win32c/055.html をみてファイルの保存ダイアログを出せるようになりました。 しかし、たまーにフリーソフトなどでもファイルを保存する際に、 デフォルトのファイル名が初期値として指定されているものもあります。 私のソフトでもそのようにしたいのですが、色々な部分に文字列を 入れてみて試してみても、思ったとおりの結果にはなりませんでした。 下記は上記サイトに記載されている ファイルを保存する際のダイアログの出し方から引用したものですが、 これをどのようにしたらダイアログが開いた際にファイル名部分に デフォルト命名された状態で開けるのでしょうか? static OPENFILENAME ofn; static TCHAR filename_full[MAX_PATH]; // ファイル名(フルパス)を受け取る領域 static TCHAR filename[MAX_PATH]; // ファイル名を受け取る領域 // 構造体に情報をセット ZeroMemory( &ofn, sizeof(ofn) ); // 最初にゼロクリアしておく ofn.lStructSize = sizeof(ofn); // 構造体のサイズ ofn.hwndOwner = hWnd; // コモンダイアログの親ウィンドウハンドル ofn.lpstrFilter = _T("text(*.txt)\0*.txt\0All files(*.*)\0*.*\0\0"); // ファイルの種類 ofn.lpstrFile = filename_full; // 選択されたファイル名(フルパス)を受け取る変数のアドレス ofn.lpstrFileTitle = filename; // 選択されたファイル名を受け取る変数のアドレス ofn.nMaxFile = sizeof(filename_full); // lpstrFileに指定した変数のサイズ ofn.nMaxFileTitle = sizeof(filename); // lpstrFileTitleに指定した変数のサイズ ofn.Flags = OFN_OVERWRITEPROMPT; // フラグ指定 ofn.lpstrTitle = _T("名前を付けて保存");// コモンダイアログのキャプション ofn.lpstrDefExt = _T("txt"); // デフォルトのファイルの種類 // 名前を付けて保存コモンダイアログを作成 if( !GetOpenFileName( &ofn ) ) { MessageBox( hWnd, _T("エラー"), _T("エラー"), MB_OK ); SendMessage( hWnd, WM_CLOSE, 0, 0 ); }

  • fread時の0xc0000005エラーについて

    現在、win32APIのGetOpenFileName()を利用して、音声ファイル(wav形式)を選択し、その選択した音声ファイルの情報を取り出すことを考えています。 プログラム自体が長いのですべて載せることが出来ないのですが、関連する部分だけピックアップすると、 main.c内で static OPENFILENAME ofn = { 0 }; static TCHAR strFile[MAX_PATH]; //ダイアログボックスが生成されたら case WM_INITDIALOG: ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hWnd; ofn.lpstrFilter = TEXT("WAVファイル(*.wav)\0*.wav\0"); ofn.lpstrFile = strFile; ofn.nMaxFile = MAX_PATH; ofn.Flags = OFN_FILEMUSTEXIST; // ファイル選択ボタンが押されたら case IDC_FILE_SELECT: //ファイルを開くダイアログを表示しwavファイルを選択 GetOpenFileName(&ofn); //選択されたファイル名(フルパス)を引数として関数に渡す if(road_wav(strFile) == FALSE) //エラー処理 ------------------ 上記の関数road_wav()は別ファイル(road_wav_file.c)で記述し、 BOOL road_wav(const char *filename){ FILE* wfp; char reafword[4]; if(fopen_s(&wfp, filename, "rb") != 0){ //エラー処理 return FALSE; } else{ //fopen_s成功 } //ここでエラー(0xc0000005) fread(reafword, 4, 1, &wfp); return TRUE; } ------------------ というように、freadの部分で0xc0000005エラーが出てしまいます。 wfpのポインタがエラーの原因かと考え、関数の引数(=選択した音声ファイル名)が間違っている、もしくは、fopen_sで正しく音声ファイルが開けていないかと思い調べてみたのですが、 strFileには選択したファイル名がフルパスで正しく格納されており、f_opensもelse側に行っている(成功している)ようなので、wfpが原因では無いようです。 しかし、他に思い当たる原因が特に無く、どの部分を直せばよいかが分からず困っております。 もし何か分かりましたら教えていただけると助かります。 説明が非常に分かりにくくなってしまい申し訳ありませんが、よろしくお願いいたします。 作業環境 Windows7 64bit Visual Studio 2013 professional

専門家に質問してみよう