2012-03-09 8 views
1

Windows APIラッパーでは、エラーが発生したときにメッセージボックスを表示するように選択できます。私は本当にピン止めできないものがある。GetWindowLongPtrが "Class already Exists"にエラーを設定します

はここに私の主な機能です:

int main() 
{ 
    Window win; //create default window with default class (name changes each new instance) 

    return messageLoop(); //the familiar GetMessage() while loop, returns msg.wParam 
} 

このすべては、私は次のメッセージが表示されます(これは私がコピーしたときに、私が得るものです正常に動作しますが、私は私のウィンドウを閉じたときに(ちょうどXボタンを経由してテストしました)メッセージボックス):このエラーはなく、正確な理由、どこから来ている

--------------------------- 
Error 
--------------------------- 
File: "G:\programming\v2\wwbasewindow.h" 
Function: _fakeWndProc 
Line: 61 
Error Code: 1410 
Error: Class already exists. 


--------------------------- 
OK 
--------------------------- 

は、今では澄みました。ここには_fakeWndProcの機能があります。この関数が呼び出された後には、wrap (function, args)の構文チェックGetLastError()がすべて呼び出されます。これがエラーチェックを表示しない理由です。

LRESULT CALLBACK BaseWindow::_fakeWndProc (msgfillparams) //trick procedure (taken from someone's gui wrapper guide) 
{ 
    BaseWindow * destinationWindowPtr = 0; //for which window message goes to 

    //PROBLEM IN THE FOLLOWING LINE (gets a pointer to the window, set when it's created) 
    destinationWindowPtr = (BaseWindow *)wrap (GetWindowLongPtr, hwnd, GWLP_USERDATA); 

    if (msg == WM_COMMAND && lParam != 0) //if control message, set destination to that window 
     destinationWindowPtr = (BaseWindow *)wrap (GetWindowLongPtr, (hwin)lParam, GWLP_USERDATA); 

    if (destinationWindowPtr) //check if pointer is valid 
     return destinationWindowPtr->_WndProc (hwnd, msg, wParam, lParam); //call window's procedure 
    else 
     return wrap (DefWindowProc, hwnd, msg, wParam, lParam); //call default procedure 
} 

この呼び出しがされて、なぜ私は思ったんだけど(クラスを作成しようとしている?)さておき、私はWM_CLOSEメッセージがやって来る時からのエラーコードをチェックしてみました。私は、行の前と後にコードを出力します。この関数はどこかに内部SendMessageを呼び出すことを暗示するよう

Before: 0 
After: 0 
--->Before: 0 
--->Before: 1410 
After: 1410 
Before: 1410 
After: 1410 
... 

これは、私の混乱にトッピング置く:これは、最大来るものです。しかし、なぜ他の人にとって同じことをしないだろうか?

エラー自体は大きな違いはありません。プログラムが終了するとすぐに終了しますが、私はそれを掛けたくありません。どうすれば対処できますか?

注: WM_DESTROYが表示されたら、私はちょうどPostQuitMessage (0);を呼び出してみませんでした。そして2つのウィンドウを作成しました。どちらもクローズ時に同じエラーが発生したため、必ずしもプログラムの終了とは限りません。

また、私はPostQuitMessageを呼び出さなかったときだけ、エラー1400(無効なウィンドウハンドル)も与えました。このエラーは、それらのウィンドウのそれぞれのウィンドウプロシージャのDefWindowProcへの呼び出しに起因しています。その上のアイデアも?

編集:

により要求に、ここwrapのコードは次のとおりです。

// pass along useful error information (useless constants within error function) 
#define wrap(...) Wrap (__FILE__, __FUNCTION__, __LINE__, __VA_ARGS__) 

// cstr == char * 
// con == const 
// sdword == int (signed dword) 

// version if return value of API function is not void 
template<typename TRet, typename... TArgs> 
typename std::enable_if<!std::is_void<TRet>::value, TRet>::type 
Wrap(con cstr file, const char * const func, con sdword line, TRet(*WINAPI api)(TArgs...), TArgs... args) 
{ 
    TRet result = api(std::forward<TArgs>(args)...); //call API function 
    if (GetLastError()) __wwError.set (GetLastError(), file, func, line); //set variables and create message box 
    return result; // pass back return value 
} 

// version if return value is void 
template<typename... TArgs> 
void Wrap(con cstr file, const char * const func, con sdword line, void(*WINAPI api)(TArgs...), TArgs... args) 
{ 
    api(std::forward<TArgs>(args)...); 
    if (GetLastError()) __wwError.set (GetLastError(), file, func, line); 
} 

私もこれと__wwError.set()作品は100%確信しています。これでラップされた他のすべての関数は、適切なメッセージボックスを与えます。

+0

ラップのコードを表示してください。 –

+0

ラップは正常に動作しているはずですが、これは少しです>>これ>そのタイプのものです。 – chris

+1

GetLastError **を呼び出していることを確認するには、** API呼び出しが失敗したときだけ**をチェックします。 –

答えて

7

GetLastErrorの呼び出しが間違っています。そのようなGetLastErrorを無差別に呼び出すことはできません。 API呼び出しのドキュメントで有効であると表示された場合にのみ呼び出すようにしてください。通常、これは、API呼び出しが失敗を報告する場合に発生します。

DefWindowProcの呼び出しは、これがどのように悪くなる可能性があるかの詳細な図です。 DefWindowProcのドキュメンテーションは、関数が失敗を報告する方法について言及していません。 GetLastErrorを呼び出すことについては言及していません。したがって、GetLastErrorへの呼び出しは行われず、定義されていない無意味な値が返されます。

Win32関数が失敗を報告するための共通のメカニズムがないため、すべてのWin32 API呼び出しを1つの一般的なエラー処理ルーチンでラップしようとすると、失敗することになります。

各API呼び出しを独自のメリットで処理し、そのAPI呼び出しに適したエラーチェックを作成する必要があります。 C++を使用しているので、ここでは例外を使用することをお勧めします。 API関数が失敗を報告するたびに呼び出す関数ThrowLastWin32Errorを記述します。 ThrowLastWin32Errorの実装は、GetLastErrorを呼び出し、FormatMessageを呼び出して適切に記述的な例外をスローする前にテキスト記述を取得します。あなたはこのようにそれを使用します。

if (!CallSomeWin32Function()) 
    ThrowLastWin32Error(); 

しかし、主なポイントは、別のWin32関数は異なる方法で失敗を報告以来、あなたはケースバイケースの機能の成功の確認が必要なのかということです。

+0

'DefWindowProc'は' GetLastError'を呼び出すことについて何も言わないかもしれませんが(そして私はそれを取り除くと思います)、 'GetWindowLongPtr'はします。私は 'foo(a)'または 'wrap(foo、a)'を使って 'GetLastError'を呼び出すかどうかを区別できます。将来、他のタイプのエラーについては、エラーのタイプに応じてテンプレートに特定のアクションを設定することができます。 'wrap'の代わりに、' win32error'、 'dxerror'、' socketerror'などの状況を使うことができます。私は今私がラップするものを通過し、不要な呼び出しを削除します。 – chris

+0

それはそれより複雑です。 GetLastErrorがメカニズムであっても、関数**が失敗した場合はGetLastErrorを呼び出すだけで意味があります**。関数が失敗を報告する方法はたくさんあります。関数が失敗し、その関数のドキュメントからGetLastErrorを呼び出すことができない限り、GetLastErrorを呼び出さないでください。 –

+0

私の骨が例外に対して選択するのは、エラーが発生する可能性があるたびに試してみなければならないということです。通話を囲むことは書いたほうがずっと少なく、繰り返しの回数が少なくなっています。私は彼らがどのようにうまくいくかを見て、何かを投げることができ、あなたが望むものを扱うことができるようになりますが、私が作るすべての呼び出しに対して追加するだけで大​​したことです。 – chris

関連する問題