.dll Question 2D Panels & LoadBitmap

  • Thread starter Thread starter ex-orbinaut
  • Start date Start date
E

ex-orbinaut

Guest
Hi,

Some help please, if possible…

I am bogged down (again) with something, and cannot find info on the threads except this one which hints towards my dilemma.

http://www.orbiter-forum.com/showthread.php?t=7969&highlight=LoadBitmap

Once more, it is something that I believe would interest other people trying to expand their SD horizons in Orbiter.
  • How exactly do you grab your 2D BitMap Panel once you have embedded it in your dll?

I am not having any problems embedding the resource. The dll, with embedded bmp, compiles and runs without a problem. It even switches to the panel view with F8, but there is no panel displayed. If I try to "scroll in" the panel with the arrow keys then, and only then, does it CTD Orbiter.

Now, I am at a loss with the following issues, and have the following doubts.

I am using VC++ 2008 Express. Is the LoadBitmap Windows API function superceded by LoadImage in VC++ 2008? Is that why it is not grabbing the bmp?

I notice the sample SDK *.rc files have the comment “//Microsoft Developer Studio generated resource script” at the top. Is it important for Orbiter that it be generated by MDS, despite the fact that embedding resources by other methods (RC.exe, for one example) is not a problem?

The crux seems to be that MAKEINTRESOURCE does not appear to be creating the bmp handle and I do not understand why. Has anyone come across this problem in VC++ 2008 or any other compiler?

Any help would be gratefully appreciated. 2D panels are an excellent way to add some polish to spaceships, but this problem is hampering my particular progress. If I do figure it out myself, I will nonetheless post the solution here, in case anyone else is finding the same obstacle insurmountable.

Thanks in advance and all the best!
 
What happens if you compile the Deltaglider or Shuttle-A sources with VC++2008? Do the panels still work then?

I haven't tried VC++2008, but at least VC++2005 doesn't have any problems with LoadBitmap.

How you create the resource file shouldn't matter. You can do it with a text editor if you like. (as long as the format is valid, of course).

Does your resource editor tell you which resources are actually available in the dll? I guess the file size should give a rough estimate. If it's smaller than the bmp file, then it didn't get embedded correctly.

Is your bmp in 8-bpp or 24-bpp format? The panels in the default samples are all 8-bpp. It's a long shot, but maybe LoadBitmap has limitations on the types of bitmaps it can load (I haven't got any windows api manuals to hand, but this should be easy to check). In any case, LoadImage should work with anything.
 
LoadBitmap should still exist. LoadImage is a different function AFAIR.
 
First of all, thank you so much, Dr. Martin, for your prompt reply, and Urwumpe for your confirmation that LoadBitmap is still supported.

To clarify the tendered points: The panel is 8 bitplane and greyscale (for the moment). It is embedding properly, as the compiled dll is almost exactly the unresourced compiled module + the bmp size. It embeds successfully two different ways, both manually with a typed (not MDS generated) **.rc file and resource.h, or with a generated **.res file, made with RC.exe.

Okay. If the LoadBitmap WinAPI function is still exists in VC++ 2008 (I will try as suggested and compile the sample ShuttleA and DG with it this evening to eliminate that possible cause), then the problem, I suspect, is the identifier that MAKEINTRESOURCE produces. So here’s something I have not tried…

There is an alternative way of grabbing the BitmapName parameter of LoadBitmap, ie; as a string. Would it be valid in Orbiter API? The Panel.rc file that I made for compilation with RC.exe read, very simply;

1 BITMAP Elopanel.bmp

What eludes me is where the identifier for the resource in the dll is, except the “1” and the string name of the file. MAKEINTRESOURCE(1) does not work. Could I do the following and expect success with the alternate method?

LoadBitmap(hDLL, Elopanel), or (hDLL, “Elopanel”)

Thank you again for the reply.

All the best,

Keith

PS. A thought. I am not specifying usage of afxres.h in any of this, apart form it being in the include directory in case it is needed. Might that be a factor?

---------- Post added at 02:36 PM ---------- Previous post was at 02:04 PM ----------

On second thoughts, I have suggested to myself what I should try. I will see how it goes this evening!

Also found some additional Windows API information regarding this at;

http://msdn.microsoft.com/en-us/library/dd183385(VS.85).aspx

---------- Post added at 07:22 PM ---------- Previous post was at 02:36 PM ----------

Hi again,

No, makes no difference. I am doing something wrong. I cut down the ShuttlePB to make a panel mock up, in case it was something ridiculous in my ship causing the problem.

And yes, the ShuttleA, with panels does compile (and work perfectly) with VC++2008, so LoadBitmap is supported. In case someone has a look, here is my code. If someone could please have a peek and point out where I am being stupid, I would be most grateful...

This is the pre RC.exe compiled panel.rc file...

Code:
// #include "resource.h" // Defunct if using RC.exe (I suspect)
// #include "afxres.h"  // Indifferent if this is used or not
PANEL   BITMAP   panel.bmp

This is the h file....

Code:
// Stand in h file created for ShuttlePB 2D Panel View Mock Up.
#ifndef __ShuttlePB_H
#define __ShuttlePB_H
#include "orbitersdk.h"

const double PB_FUELMASS = 750.0;

//===============================================================
class ShuttlePB: public VESSEL2 {
public:
    ShuttlePB (OBJHANDLE hVessel, int flightmodel)
        : VESSEL2 (hVessel, flightmodel) {}
    
    void clbkSetClassCaps (FILEHANDLE cfg);
    bool clbkLoadPanel (int id);

    HINSTANCE hDLL;
    HBITMAP hBmp;  // It does not seem to mind the redefinition. That's suspect.
    PROPELLANT_HANDLE hpr;
//    THRUSTER_HANDLE th_main, th_hover, th_rcs[14], th_group[4];

};
//typedef struct {
//    HINSTANCE hDLL;
//    HFONT hFont[1];
//    HPEN hPen[2];
//    HBRUSH hBrush[1];
//} GDIParams;
//  I only need the HINSTANCE for the panel load itself, as yet..
#endif 

// #define PANEL  1 // only required if MAKEINTRESOURCE is used in LoadBitmap(*,*)

...and finally, here's the cpp...

Code:
// ==============================================================
//                 ORBITER MODULE: ShuttlePB
//                  Part of the ORBITER SDK
//          Copyright (C) 2002-2004 Martin Schweiger
//                   All rights reserved
//
// ShuttlePB.cpp
// Mock up to test 2D Panel View modded by Keith Shearer, June 2009

#define STRICT 1
#define ORBITER_MODULE
// #include "orbitersdk.h"
#include "ShuttlePB.h"
//#include "resource.h" // Not used when **.res compiled by RC.exe
#include <stdio.h>
#include <math.h>

void ShuttlePB::clbkSetClassCaps (FILEHANDLE cfg)
{
    SetSize (3.5);
    SetEmptyMass (500.0);
    SetCameraOffset (_V(0,0.8,0));
    SetTouchdownPoints (_V(0,-1.5,2), _V(-1,-1.5,-1.5), _V(1,-1.5,-1.5));
    // propellant resources
    hpr = CreatePropellantResource (PB_FUELMASS); // Not used in Mock Up
    SetMeshVisibilityMode (AddMesh (("ShuttlePB")), MESHVIS_EXTERNAL);
    //AddMesh ("ShuttlePB");
}
// ==============================================================
bool ShuttlePB::clbkLoadPanel (int id)
{
    // HBITMAP hBmp = LoadBitmap (hDLL, MAKEINTRESOURCE(PANEL));
    HBITMAP hBmp = LoadBitmap (hDLL, "panel"); // I redefined hBmp here
    // as an HBITMAP, but it does not seem to mind. That is odd....
    oapiRegisterPanelBackground (hBmp);
    return true;
}
//=============================================================
DLLCLBK VESSEL *ovcInit (OBJHANDLE hvessel, int flightmodel)
{
    return new ShuttlePB (hvessel, flightmodel);
}
//=============================================================
DLLCLBK void ovcExit (VESSEL *vessel)
{
    if (vessel) delete (ShuttlePB*)vessel;
}

That's all.

Thanks in advance...

Keith
 
Ok, I am slightly confused. I see that you use "PANEL" as a literal string to identify the bitmap resource. I am not familiar with that method, but is it possible that the check is case-sensitive? In that case, "panel" may have to be replaced with "PANEL".

But using an integer identifier should definitely work. Just to confirm:
You did have

#define BITMAP 1

in resource.h, and included resource.h in both the rc and the cpp file? If you didn't include it in the rc file, then "PANEL" may have been interpreted as a literal string in the rc file, and as an integer in the cpp file, and that could not have worked.

Your comment seems to indicate that the #include directive may not be supported with rc.exe. But in that case, the Shuttle-A sources would probably not have compiled properly.

Another possibility is that certain resource identifiers are reserved. When I let VC automatically generate the identifiers, they usually start at values > 100. Try #define PANEL 100 and see if that makes a difference.
 
Dr. Martin, thank you so much once again for your kind attention to this issue, and my sincere apologies for my being vague. This is my first ever venture into using bitmaps in C type programming, even counting my out of date and largely forgotten dabbling in C yonks ago.

Since my last post, I am reasonably satisfied that one of the main errors is in the preprocessor directive, too. I have been somewhat hampered for clarity, also, by the fact that the Express edition of VC++ 2008 does NOT support resource viewing or editing, so as to be able to put a tack on what is going on in (or even into) the dll.

I now have a solution to that aspect in that I have tracked down a free resource viewer at;

http://download.cnet.com/Nasser-Resource-Viewer/3000-2383_4-10591555.html

I will be using it this evening to analyze the *.res file or even the dll, and positively track down the resource id in there.

About the define directive; it was #define BITMAP 1 in the resource.h, for the manual, not RC.exe generated version. And yes, I have been using the string identifier alternative incorrectly, too. Thank you for confirming it, as I was not 100% sure. The misleading thing is that the dll compiles and works great, but no panel. Just the same, I will revert and stick to the MAKEINTRESOURCE macro for getting the Bitmap, as rightly suggested.

I suspect that I am on the right track now, after some valuable guidance on the theme! Thank you again for your all of your help, Dr. Martin! It is MOST appreciated.

All the best,

Keith

PS. Will follow up this post with results if I meet with success, for the benefit of other users of VC++ 2008 Express who might be having the same problems.

---------- Post added at 11:25 AM ---------- Previous post was Yesterday at 12:43 PM ----------

Quick update on this one...



Still no joy. But the follwoing IS resolved.
  • A quick check with the VB6 resource compiler proved that, yes, id's for resources are automatically assigned as from 101 by MSDev, even this older and different platform version.
  • I made a separate win32.exe program, totally apart from Oapi, in VC++2008 and there does seem to be a problem with grabbing resources with LoadBitmap. The resources are there, perfectly (Nasser Viewer even shows you what it is, so there is no doubt), but still unable to get the BitMap. The perplexing thing remains as to why the ShuttleA compiles okay on it (more thoughts in a second).
I have not exhausted options yet, however. I am beginning to wonder if its not a library/header thing in the compiler setup. The LPCSTR string data type (in the win.exe prog) caused some problems, for one.

The ShuttleA compiles okay if you use the project that comes with it, which VC++ 2008 converts when you first open it. Looking at the set up options, there is a reference to a precompiled header (*.pch), but one that strangely cannot be located where it says it is (?!). Also, there is some language support set in the compiler for ShuttleA (English (United Kingdom)). Does not seem likely, but as it is also described in the ShuttleA.rc file, I am wondering if this is a factor.

Finally, there seems to be a specific inclusion of orbiter.lib and orbitersdk.lib as project elements (in the project explorer window). That does seem a long shot, though, as, these libs are already included in the additional lib settings in my set up.

Under certain configurations (sorry, have not put my finger exactly on which yet) the compiler tries to interpret the HINSTANCE as an identifier, and throws and error stating it is an "undeclared identifier".

To surmize; seems likely that there is some platformSDK header or lib file that my project is missing, skipping, or cannot find. So, a trolling/combing task for the weekend.

Success will be next post! Standby....

PS. If anyone is following this thread, I will add that I am going to be trying specific inclusion of winuser.h, as this is the required header for the LoadBitmap / LoadImage functions and it does not appear to be linking by default.
 
Last edited by a moderator:
picture.php



Solved....

Celebrations, but what an idiot I am!!!

Code:
// ==============================================================
//                 ORBITER MODULE: ShuttlePB
//                  Part of the ORBITER SDK
//          Copyright (C) 2002-2004 Martin Schweiger
//                   All rights reserved
//
// ShuttlePB.cpp
// Mock up to test 2D Panel View modded by Keith Shearer, June 2009
 
#define STRICT 1
#define ORBITER_MODULE
// #include "orbitersdk.h"
#include "ShuttlePB.h"
//#include "stdafx.h"
#include "winuser.h" // This is not REALLY required, in fact....
//#include <afxres.h>
//#include <Windows.h>
#include "resource.h" // Not used when **.res compiled by RC.exe
#include <stdio.h>
#include <math.h>
 
ShuttlePB::ShuttlePB (OBJHANDLE hVessel, int flightmodel)
: VESSEL2 (hVessel, flightmodel)
{
}
ShuttlePB::~ShuttlePB ()
{
}
void ShuttlePB::clbkSetClassCaps (FILEHANDLE cfg)
{
 SetSize (3.5);
 SetEmptyMass (500.0);
 SetCameraOffset (_V(0,0.8,0));
 SetTouchdownPoints (_V(0,-1.5,2), _V(-1,-1.5,-1.5), _V(1,-1.5,-1.5));
 // propellant resources
 hpr = CreatePropellantResource (PB_FUELMASS); // Not used in Mock Up
 SetMeshVisibilityMode (AddMesh (("ShuttlePB")), MESHVIS_EXTERNAL);
 //AddMesh ("ShuttlePB");
}
// ==============================================================
bool ShuttlePB::clbkLoadPanel (int id)
{
 //LPCSTR PANEL; Why not???!!!
 //PANEL = "101"; Yes, but what module?
 //oapiRegisterPanelBackground (LoadBitmap (hDLL, "IDB_PANEL"),PANEL_ATTACH_BOTTOM|PANEL_MOVEOUT_BOTTOM, 0xFFFFFF);
 //oapiRegisterPanelBackground (LoadBitmap (hDLL, "101"),PANEL_ATTACH_BOTTOM|PANEL_MOVEOUT_BOTTOM, 0xFFFFFF); Nope...

// This one works now.....
 
HBITMAP hBmp = LoadBitmap(hDLL, MAKEINTRESOURCE( IDB_PANEL ));
 
return true;
}
 
DLLCLBK void InitModule (HINSTANCE hModule)
{
 hDLL = hModule;
 
}
 
DLLCLBK void ExitModule (HINSTANCE hModule)
{
 
}
 
DLLCLBK VESSEL *ovcInit (OBJHANDLE hvessel, int flightmodel)
{
 return new ShuttlePB (hvessel, flightmodel);
 
}

DLLCLBK void ovcExit (VESSEL *vessel)
{
 if (vessel) delete (ShuttlePB*)vessel;
}

Okay. It goes without saying that you have to specify the handle for the dll instance before you can load ANY bitmap from it. Look at the InitModule callback.

hDLL = hModule;

Found it eventually not by looking at the sample code, but by using the Win API GetModuleHandle() function, and suddenly it worked! In asking myself why, saw what I was missing in the original code. Anyway, you can see the fun I have had.

My sincere thanks again to Dr. Martin for the help, and for the sim itself. It is entertaining and educational in more ways than one.

Sorry to have been a numpty!

All the best,

Keith
 
BTW, going back a bit in this same thread....

LoadBitmap() does work in Orbiter with the string option instead of the MAKEINTRESOURCE macro. The <cstring> header must be #included (so that strcpy() is available), and the string needs to be NULL terminated. Here's the example snippet that works.


Code:
bool PanelledVessel::clbkLoadPanel (int id)
{
    char str[10];
    strcpy(str, "PANEL");
    
    HBITMAP hBmp = LoadBitmap(hDLL, str);
    
    oapiRegisterPanelBackground (hBmp, PANEL_ATTACH_BOTTOM|PANEL_MOVEOUT_BOTTOM, 0xffffff);
    
    return true;
}

If you use RC.exe, there is no need to make a resource file, just the ***.rc file, which is compiled with RC.exe to produce the ***.res file, which you include in your compile. More info on how this is done in the OrbiterWikiFree Compiler Set Up help article.

I am not sure if it might improve the speed of execution, however, by avoiding the macro. Probably not...

Think that wraps it up for this thread, :cheers:

Thanks.
 
BTW, going back a bit in this same thread....

LoadBitmap() does work in Orbiter with the string option instead of the MAKEINTRESOURCE macro. The <cstring> header must be #included (so that strcpy() is available), and the string needs to be NULL terminated. Here's the example snippet that works.

Code:
bool PanelledVessel::clbkLoadPanel (int id)
{
    char str[10];
    strcpy(str, "PANEL");
 
    HBITMAP hBmp = LoadBitmap(hDLL, str);
 
    oapiRegisterPanelBackground (hBmp, PANEL_ATTACH_BOTTOM|PANEL_MOVEOUT_BOTTOM, 0xffffff);
 
    return true;
}

If you use RC.exe, there is no need to make a resource file, just the ***.rc file, which is compiled with RC.exe to produce the ***.res file, which you include in your compile. More info on how this is done in the OrbiterWikiFree Compiler Set Up help article.

I am not sure if it might improve the speed of execution, however, by avoiding the macro. Probably not...

Think that wraps it up for this thread, :cheers:

Thanks.
Out of curiousity, why can't you just do this?
Code:
bool PanelledVessel::clbkLoadPanel (int id)
{
    HBITMAP hBmp = LoadBitmap(hDLL, "PANEL");
 
    oapiRegisterPanelBackground (hBmp, PANEL_ATTACH_BOTTOM|PANEL_MOVEOUT_BOTTOM, 0xffffff);
 
    return true;
}
The compiler should see the same thing....
 
Hi, Hielor.

Yeah, I had tried it but it was not working, but maybe here's why. When I did try it, I had not included cstring header. It could be that. Will try it. Thanks!

EDIT:
Just adding a quick note edit fashion as not to bump the post unduly, but for the benefit of anyone who might be having problems with LPCWSTR type errors when working with strings (for loading bmps, etcetera) who reads this post. I do not like leaving untied ends...

This problem kept rearing its head in other compile operations that used strings in VC++ 2008 Express (at least). The MAIN problem that causes this type of error is not the use of headers as much as it is a compiler configuration issue. Make sure the character set is not UNICODE (set it to Multi Byte character set in the compiler properties), and if needed, typecast the string to the required data type. Solves 99% of the problems, even if you are doing Windows API application development.

I repeat this edit in another thread where I address the same problem, just in case.
 
Last edited by a moderator:
Back
Top