2017-05-10 6 views
1

私はVisual Studioを使ってC++のGUIを作成する方法を学ぼうとしています。 GetWindowText()関数を使用しているときにいくつか問題が発生しました。 LPTSTRのタイトルはテキストボックスのテキストに変更されず、「Win32Project1.exeの0x74F8207D(user32.dll)で例外がスローされました:0xC0000005:0x002B8D38という場所のアクセス違反」というデバッグ時にエラーが発生します。私は何が間違っているの下に見える?GetWindowText malfunktion

#define ID_BUTTON1 1 
#define ID_BUTTON2 2 
#define ID_TEXT3 3 
static HWND hWndTextbox; 
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 
{ 
switch (message) 
{ 
case WM_CREATE: 
{ 
    HMENU hMenubar = CreateMenu(); 
    HMENU hFile = CreateMenu(); 
    HMENU hOptions = CreateMenu(); 

    AppendMenu(hMenubar, MF_POPUP, (UINT_PTR)hFile, L"File"); 
    AppendMenu(hMenubar, MF_POPUP, NULL, L"Edit"); 
    AppendMenu(hMenubar, MF_POPUP, (UINT_PTR)hOptions, L"Options"); 

    AppendMenu(hFile, MF_STRING, NULL, L"Exit"); 
    AppendMenu(hOptions, MF_STRING, NULL, L"option 1"); 
    AppendMenu(hOptions, MF_STRING, NULL, L"option 2"); 
     SetMenu(hWnd, hMenubar); 

    CreateWindow(TEXT("button"), TEXT("Hello"), 
     WS_VISIBLE | WS_CHILD, 
     10, 10, 80, 25, 
     hWnd, (HMENU) ID_BUTTON1, NULL, NULL); 

    static HWND hWndTextbox = CreateWindow(TEXT("edit"), TEXT("tekst goes here"), 
     WS_VISIBLE | WS_CHILD|WS_BORDER | ES_AUTOHSCROLL, 
     90, 120, 300, 20, 
     hWnd, (HMENU) ID_TEXT3, NULL, NULL); 

    CreateWindow(TEXT("button"), TEXT("shiny"), 
     WS_VISIBLE | WS_CHILD, 
     50, 50, 80, 50, 
     hWnd, (HMENU) ID_BUTTON2, NULL, NULL); 
} 
break; 
case WM_COMMAND: 
    { 
    if (LOWORD(wParam) == ID_BUTTON1) { 
     MessageBox(hWnd, L"Button has been clicked", L"title for popup", MB_ICONINFORMATION); 
    } 
    if (LOWORD(wParam) == ID_BUTTON2) { 
     // create some default vars 
     // int length = GetWindowTextLength(hWndTextbox) + 1; 
     LPTSTR title = L"test" ; 

     GetWindowText(hWndTextbox, title, GetWindowTextLength(hWndTextbox) + 1); 
     MessageBox(hWnd, title, L"Message box", MB_OK); 
    } 
    break; 
     int wmId = LOWORD(wParam); 
     // Parse the menu selections: 
     switch (wmId) 
     { 
     case IDM_ABOUT: 
      DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); 
      break; 
     case IDM_EXIT: 
      DestroyWindow(hWnd); 
      break; 
     default: 
      return DefWindowProc(hWnd, message, wParam, lParam); 
     } 
    } 
    break; 
case WM_PAINT: 
    { 
     PAINTSTRUCT ps; 
     HDC hdc = BeginPaint(hWnd, &ps); 
     // TODO: Add any drawing code that uses hdc here... 
     EndPaint(hWnd, &ps); 
    } 
    break; 
case WM_DESTROY: 
    PostQuitMessage(0); 
    break; 
default: 
    return DefWindowProc(hWnd, message, wParam, lParam); 
} 
return 0; 
} 

コードの残りの部分は、私は、私は変更を加えた部分のみが含まれているのVisual Studioによって自動生成しました。

+0

あなたはリテラル文字列を変更することになっていない、私はそれは未定義の動作だと信じています。代わりに 'char'または' wchar_t'(または 'TCHAR')配列を設定してください。 –

答えて

1

GetWindowText()のドキュメントには、パラメータlpString書き込み可能バッファを意味し、「それはテキストを受け取るバッファ」を指すようになっていると述べています。

コードLPTSTR title = L"test";では、通常は読み取り専用メモリに置かれている文字列リテラルへのポインタを作成します。 GetWindowText()がそのメモリに書き込もうとすると、アクセス違反が発生します。 、この問題を解決するため、このような書き込み可能なバッファを使用するには

// Allocate buffer including terminating null 
std::wstring title(GetWindowTextLength(hWndTextbox) + 1, 0); 

// Address of first character is used to obtain pointer to non-const data 
// (as opposed to wstring::c_str()). 
int size = GetWindowText(hWndTextbox, &title[0], title.size()); 

// Resize buffer to the actual text length 
title.resize(size); 

// MessageBox only needs pointer to const string, so we can use wstring::c_str() here. 
MessageBox(hWnd, title.c_str(), L"Message box", MB_OK); 
関連する問題