2011-04-30 111 views
3

我試圖使winapi功能的包裝GetWindowText。 函數返回std :: wstring,但我不知道如何處理髮生錯誤的地方。我返回NULL,但我知道這是錯誤的。函數返回std :: wstring = NULL;

std::wstring GetWindowText(HWND handle) 
{ 
    const int size = 1024; 
    TCHAR wnd_text[size] = {0}; 

    HRESULT hr = ::GetWindowText(handle, 
        wnd_text, size); 
    if(SUCCEEDED(hr)) 
     return std::wstring(wnd_text); 
    else 
     return NULL;  
} 
+3

NULL僅用於指針。 – Alex 2011-04-30 20:49:45

回答

5

作爲替代的例外,你還可以通過引用參數列表返回字符串,並通過返回true或false即表明sucess

bool GetWindowText(HWND handle, std::wstring& windowText) 
{ 
    const int size = 1024; 
    TCHAR wnd_text[size] = {0}; 

    HRESULT hr = ::GetWindowText(handle, 
        wnd_text, size); 
    if(SUCCEEDED(hr)) 
    { 
     windowText = wnd_text; 
     return true; 
    } 
    else 
     return false;  
} 

避免了引用參數的另一種替代方案是返回的一個實例一個包裝值的類,但也讓你知道一個值是否存在,例如

class ValueWrapper 
{ 
public: 
    ValueWrapper() : present(false) {} 
    ValueWrapper(const std::wstring& s) : value(s), present(true) {} 

    bool isPresent() const { return present; } 
    const std::wstring& getValue() const { return value; } 

private: 
    std::wstring value; 
    bool present; 
}; 

請注意,你可以很容易地模板這個包裝。您的功能將然後是

ValueWrapper GetWindowText(HWND handle) 
{ 
    const int size = 1024; 
    TCHAR wnd_text[size] = {0}; 

    HRESULT hr = ::GetWindowText(handle, 
        wnd_text, size); 
    if(SUCCEEDED(hr)) 
     return ValueWrapper(wnd_text); 
    else 
     return ValueWrapper(); 
} 
+2

請注意['boost :: optional <>'](http://www.boost.org/doc/libs/release/libs/optional/doc/html/index.html)是一個預先存在的,經過測試的' ValueWrapper'。 – ildjarn 2011-04-30 21:03:24

+0

@ildjarn:謝謝。我不知道。 – Troubadour 2011-04-30 21:04:52

+0

請注意'boost :: optional <>'在這種情況下有一個誤導性的名字---這裏的常規名稱是'Fallible'。 (另外,可以擴展一個'Fallible',以便它包含有關錯誤的其他信息。) – 2011-04-30 23:11:55

7

改爲拋出exception

std::wstring GetWindowText(HWND handle) 
{ 
    const int size = 1024; 
    TCHAR wnd_text[size] = {0}; 

    HRESULT hr = ::GetWindowText(handle, 
        wnd_text, size); 
    if(SUCCEEDED(hr)) 
     return std::wstring(wnd_text); 
    else 
     throw std::runtime_error("insert error message here");  
} 
+0

不要以爲這是個好主意。一般winapi函數不會拋出異常。最好通過SetLastError()設置最後的錯誤http://msdn.microsoft.com/en-us/library/ms680627(v=vs.85).aspx – 2011-04-30 20:48:06

+5

@Mihran:這是一個* C++ *包裝器,所以用C++習慣用法來轉換WinAPI習語是正確的。如果它將'GetLastError'值封裝在特定的異常類型中會更好。 – 2011-04-30 20:53:09

+0

在這種情況下,他仍然必須返回一個值。它應該是什麼樣的價值?另外,每次調用這個函數後調用'GetLastError'都比捕獲一個異常更加醜陋。 – 2011-04-30 20:53:43

0

NULL絕對是 OK的字符串,你是專門不允許空指針傳遞到字符串構造函數。

如果您不想拋出異常,則可以返回空字符串return std::wstring();

+2

但是,如果問題的字符串實際上是空的,它將導致一個假的錯誤。 – 2011-04-30 20:56:11

+1

@Grigory - 它可能,是的,取決於接口定義的是什麼。但是,std :: wstring(NULL)是**總是**錯誤,因爲它違反語言標準! – 2011-04-30 21:01:23

0

WinApi的設計,使它永遠不會拋出異常。並且爲了獲得一些不成功的返回某些功能的原因,你在大多數情況下必須通過GetLastError()得到最後的錯誤。據我瞭解,你的功能將成爲WinApi的一個補充,這將很容易使用。所以我建議保持他們的設計。即在失敗的情況下返回空字符串,並檢查函數是否返回最後一個錯誤。

1

另一個解決方案(不拋出異常):使用Boost.Optional庫。

+0

+1我喜歡這個。 – 2011-04-30 21:12:20

0

首先GetWindowText()不返回HRESULT,所以你的代碼在這方面是錯誤的。

第二,GetWindowTextW在任何錯誤或字符數上返回0(如果確定)。 所以才返回一個空字符串:

std::wstring GetWindowText(HWND handle) 
{ 
    const int size = 1024; 
    TCHAR wnd_text[size] = {0}; 

    INT n = ::GetWindowTextW(handle, 
        wnd_text, size); 
    if(n > 0) 
     return std::wstring(wnd_text,n); 
    else 
     return std::wstring(); 
} 
0

根據您的應用程序中,有幾個合適的 解決方案。第一種是在出現 錯誤的情況下拋出異常:如果你走這條路,你應該定義一個WindowsError 例外(來源於其中一個標準例外),其中 包括GetLastError, 的所有可用信息和可能的附加信息(功能的名稱,其中 失敗等),以易於解析的格式。另一種是 返回某種Fallible;在這種情況下,您可能想要 擴展古典Fallible慣用語,以便它可以包含有關錯誤原因的其他信息 。仍然 另一種可能性是通過輸出參數 返回值,並使用返回碼(可能還有其他 信息,並且可能添加了代碼以確保它在被破壞前已被測試過)。