Positive thinking
Simplify the problem
Use a debugger
Use logging functions
Use the wxWindows debugging facilities
Check Windows debug messages
Genetic mutation
It is common to blow up the problem in one's imagination, so that it seems to threaten weeks, months or even years of work. The problem you face may seem insurmountable: but almost never is. Once you have been programming for some time, you will be able to remember similar incidents that threw you into the depths of despair. But remember, you always solved the problem, somehow!
Perseverance is often the key, even though a seemingly trivial problem can take an apparently inordinate amount of time to solve. In the end, you will probably wonder why you worried so much. That's not to say it isn't painful at the time. Try not to worry -- there are many more important things in life.
Reduce the code exhibiting the problem to the smallest program possible that exhibits the problem. If it is not possible to reduce a large and complex program to a very small program, then try to ensure your code doesn't hide the problem (you may have attempted to minimize the problem in some way: but now you want to expose it).
With luck, you can add a small amount of code that causes the program to go from functioning to non-functioning state. This should give a clue to the problem. In some cases though, such as memory leaks or wrong deallocation, this can still give totally spurious results!
This sounds like facetious advice, but it is surprising how often people don't use a debugger. Often it is an overhead to install or learn how to use a debugger, but it really is essential for anything but the most trivial programs.
There is a variety of logging functions that you can use in your program: see Logging functions.
Using tracing statements may be more convenient than using the debugger in some circumstances (such as when your debugger doesn't support a lot of debugging code, or you wish to print a bunch of variables).
You can use wxDebugContext to check for memory leaks and corrupt memory: in fact in debugging mode, wxWindows will automatically check for memory leaks at the end of the program if wxWindows is suitably configured. Depending on the operating system and compiler, more or less specific information about the problem will be logged.
You should also use debug macros as part of a 'defensive programming' strategy, scattering wxASSERTs liberally to test for problems in your code as early as possible. Forward thinking will save a surprising amount of time in the long run.
See the debugging overview for further information.
Under Windows, it is worth running your program with DbgView running or some other program that shows Windows-generated debug messages. It is possible it will show invalid handles being used. You may have fun seeing what commercial programs cause these normally hidden errors! Microsoft recommend using the debugging version of Windows, which shows up even more problems. However, I doubt it is worth the hassle for most applications. wxWindows is designed to minimize the possibility of such errors, but they can still happen occasionally, slipping through unnoticed because they are not severe enough to cause a crash.
If we had sophisticated genetic algorithm tools that could be applied to programming, we could use them. Until then, a common -- if rather irrational -- technique is to just make arbitrary changes to the code until something different happens. You may have an intuition why a change will make a difference; otherwise, just try altering the order of code, comment lines out, anything to get over an impasse. Obviously, this is usually a last resort.