Basic Win32 and DX9 questions

Started by
7 comments, last by Emmanuel Deloget 17 years, 6 months ago
Hi! After playing around with Managed DirectX for a while (the result can be seen here) I decided it´s time to go down and dirty with som real C++ DirectX9. I have a few questions though: 1. There seems to be a gazillion different ways to declare a main function in Win32. Sometimes it´s just "WinMain", somtimes it´s "wWinMain", I think I saw an "lWinMain" too. Sometimes people put WINAPI in front of the name, sometimes it´s APIENTRY. What is the difference between these? Is there any? 2. One thing I always hated with C++ is that there is a hundred different string types. In a D3D book I have texts are always entered as TEXT("some text") that, if I understand correctly has something to do with Unicode? Now, what kind of text class should I use with my D3D applications. Or should I even make my own? I have used CString in the past, but that´s MFC, right? 3. Is it really stupid of me to start learning DX9 at the moment, when DX10 is right around the corner? As I understand DX10 is quit different from DX9. Should I just start fooling around with the DX10 beta? Thanks in advance! //chinc [Edited by - chinc on October 20, 2006 3:08:08 AM]
Advertisement
There is only one WinMain and it's:
int WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);

and must be declared using the __stdcall attribute - CALLBACK and WINAPI are macros defined by <windows.h> that set up that calling convention. The trouble with WinMain is that it only accepts ASCII strings, Unicode applications must call GetCommandLine to get a Unicode version of the command line. MFC defined a helper called wWinMain that did provide Unicode parameters. lWinMain I've not seen before.

The TEXT("string") is another macro defined by <windows.h> which creates either an ASCII string or a Unicode string depending on the build settings.

As for which version to learn, DX10 is going to far simpler to program for - there are no capability flags anymore. DX10 compliant hardware must meet a fixed specification and produce a well defined output. DX10 is only available as far as I know on the Vista platform. So, going for DX10 is going to be fairly niche on two fronts - not many hardware cards and not many OSs. DX9 on the other hand is a bit trickier but is well understood by the community and there are plenty of references to get help from.

Skizz
Just to add more confusion to the WinMain mix, when VSExpress creates a default new Windows Application, it gives you _tWinMain (or something like that) which I assume is like TEXT and resolves to the correct WinMain depending on UNICODE settings.
Quote:Original post by chinc
Hi!

After playing around with Managed DirectX for a while (the result can be seen here) I decided it´s time to go down and dirty with som real C++ DirectX9. I have a few questions though:

1. There seems to be a gazillion different ways to declare a main function in Win32. Sometimes it´s just "WinMain", somtimes it´s "wWinMain", I think I saw an "lWinMain" too. Sometimes people put WINAPI in front of the name, sometimes it´s APIENTRY. What is the difference between these? Is there any?

As other said, sometimes the compiler settings are used to map a #define'd WinMain name (such as _tWinMain) to the real one, depending on whether you use unicode or not. The entry point of a unicode application is not WinMain - although it is a related function with a similar name.

Quote:2. One thing I always hated with C++ is that there is a hundred different string types. In a D3D book I have texts are always entered as TEXT("some text") that, if I understand correctly has something to do with Unicode? Now, what kind of text class should I use with my D3D applications. Or should I even make my own? I have used CString in the past, but that´s MFC, right?

CString is a MFC thingy (and quite a bad one, IMHO). If you want to use C++ strings, I suggest you to use std::string and std::wstring. If you don't know if your app will be unicode or sbcs/mbcs, I suggest you to typedef them using something along the line of
#ifdef UNICODEtypedef std::wstring tstring;#elsetypedef std::string tstring;#endif

For my own purpose, I made a tstd namespace that contain such kind of type definition:
namespace tstd{#ifdef UNICODE#ifndef TEXT#define TEXT(t) L##t#endiftypedef std::wstring tstring;typedef std::ostream tostream;// same thing for wide-char io streamsnamespace { tostream& tcout = std::wcout; }// same for the other global variables of the CSL  (wcin, wcerr, wclog)#else#ifndef TEXT#define TEXT(t) t#endiftypedef std::string tstring;typedef std::ostream tostream;// same thing for non-unicode io streamsnamespace { tostream& tcout = std::cout; }// same for the other global variables of the CSL (cin, cerr, clog)#endif};

This way, I can use std::tostream, tstd::tcout or tstd::tstring in conjunction with the TEXT() macro.
Beside that, there is not a hundred bazillion string type: there is the standard C++ one, and some libraries happen to offer new, often sub-optimal implementation of some kind of string class. The char* thingy defines a pointer to a character which may be used to point to the beginning of an asciiz string, but that's hardly a real string object [smile] (and you should avoid it)

Quote:3. Is it really stupid of me to start learning DX9 at the moment, when DX10 is right around the corner? As I understand DX10 is quit different from DX9. Should I just start fooling around with the DX10 beta?

You can learn DX10, but remember it will be only available in Vista. The next release of DX for XP is coming though (it is called DirectX 9.0L, and I believe it will also be in Vista). It will enable shader model 4.0 for DX10-class hardware used in XP.

Regards,
Wow, that piece of code seems cool but I don´t really understand it. How should I then declare a string? This way?
tstd::tstring someString = TEXT("hello world!");

Also what is LPCSTR and the like that MSDN is full of? Pointers to strings of different kinds? For example the D3DXGetImageInfoFromFile-function in DirectX is:
HRESULT WINAPI D3DXGetImageInfoFromFile{    LPCSTR pSrcFile,    D3DXIMAGE_INFO *pSrcInfo};

What kind of string is pSrcFile? Can I use it directly with a tstd-string?

Thanks!
//chinc
The API documentation for LPCSTR is:
Quote:
Pointer to a constant null-terminated string of 8-bit Windows (ANSI) characters.

So it will always be 8 bit characters regardless of the Unicode settings.

The platform SDK documentation (which is free from here) has this in it.

Skizz
Quote:Original post by chinc
Also what is LPCSTR


Long Pointer to a Const STRing. The Long part is compatibility with the names for types used by 16-bit Windows (which had long and short pointers because a 16-bit pointer can only address 65536 different addresses), and doesn't mean anything any more. It's typedefed to const char* under Win32, I think. LPCWSTR is the unicode equivalent.
Quote:Original post by chinc
Wow, that piece of code seems cool but I don´t really understand it. How should I then declare a string? This way?
tstd::tstring someString = TEXT("hello world!");



Yep, more or less just like that.

Quote:
Also what is LPCSTR and the like that MSDN is full of? Pointers to strings of different kinds? For example the D3DXGetImageInfoFromFile-function in DirectX is:
HRESULT WINAPI D3DXGetImageInfoFromFile{    LPCSTR pSrcFile,    D3DXIMAGE_INFO *pSrcInfo};



LPCSTR is a typedef. it's typedef'ed as const char* and is one and the same. They are pointers to chars just like what Emmanuel mentioned. MS has this habit of typedefing all their types. So for example a LPD3DXIMAGE_INFO is actually just a D3DXIMAGE_INFO* and an LPCD3DXIMAGE_INFO would be a const D3DXIMAGE_INFO*. It's a pretty common convention used throughout the Win32 api and DirectX.


Quote:
What kind of string is pSrcFile? Can I use it directly with a tstd-string?

Thanks!
//chinc


It depends, if you are not in unicode mode then yes you can use it with tstring. Because in non-unicide tstring is defined as an std::string which accepts char*'s as certain arguments. If UNICODE was defined then tstring would become a std::wstring which does not accept char*, instead it accepts wchar_t* (in visual c++).

wchar_t* is a pointer to wchar's (wide chars - which are generally 2 bytes instead of the 1 byte for a char, this allows you to represent a larger range of alphabets then a char does, after all, you can't really fit the chinese language inside a chr can you :smile:)

[size=2]aliak.net
LPCSTR = Long Pointer to Constant STRing. This is a char*. LPCWSTR is a Long Pointer to Constant Wide STRing. LPCTSTR is a pointer to a T string (meaning is can map to either a LPCSTR or a LPCWSTR).

If you have to use LPCSTR with t-strings, you have to convert the string to a t-string (because you don't know if the t-string is a normal string or a wide one). This can't be avoided, but it can be easily encapsulated into a bunch of simple-to-use functions.

This is done using the standard functions wcstombs and mbstowcs:
namespace tstd{#ifdef UNICODEinline tstring wstr_to_tstr(const std::wstring& in){  // tstring is a wstring  return in;}inline tstring str_to_tstr(const std::string& in){  // tstring is a wstring  tstring out(in.length());  mbstowcs(const_cast<wchar_t*>(out.c_str()), in.c_str(), in.length());  return out;}// need also to do the inverse operation : tstr_to_str, tstr_to_wstr#elseinline tstring wstr_to_tstr(const std::wstring& in){  // tstring is a wstring  tstring out(in.length());  wcstombs(&out[0], in.c_str(), in.length());  return out;}inline tsrting str_to_str(const std::string& in){  // tstring is a string  return in;}// need also to do the inverse operation : tstr_to_str, tstr_to_wstr#endif

The code is now quite easy: whenever the library I use want a LPCSTR, the only thing I need to do is:
tstd::tstring my_string;the_library_function(tstd::tstr_to_str(my_string).c_str());

The created copy is local to the current block and will be destroyed when the block ends, so this code can't be used to create a string that will live out of scope (the LPCSTR will live as ling as the return value of tstr_to_str lives).

It's quite easy to use [smile]

This topic is closed to new replies.

Advertisement