Jump to content
Sign in to follow this  
n4gix

Owner drawn gauge help

Recommended Posts

Guest jcleland

Hi,I have an owner drawn gauge that consists of a static lib containing the instrument logic (C++), a C wrapper, and a DLL project that builds the gauge. The gauge has a digital screen that is green and part of the background bitmap. I'm trying to load a gauge background from a bitmap using MAKE_STATIC and pass the DC into my C++ object to render the contents of the gauge 'screen', effectively writing black pixels on top of the green background of the gauge bitmap. I have used the Flightmap example from the SDK and gotten only so far, but I don't see the data that I'm writing to the element dc. I write to the dc prior to passing it off to SET_OFF_SCREEN(). I intentionally isolated the gauge logic to a lib so that I could build a win32 test harness for it. The win32 app works fine and I'm kinda confused. Does anyone have an example that might help?Thanks!

Share this post


Link to post
Share on other sites
Guest _ak

check that you have set IMAGE_CREATE_DIBSECTION flag and no IMAGE_USE_TRANSPARENCY flag

Share this post


Link to post
Share on other sites
Guest jcleland

Thanks for the reply. I was using IMAGE_USE_TRANSPARENCY, and I changed this to IMAGE_CREATE_DIBSECTION for my background static. Now, FS is dumping to desktop when I start a flight. I'm not sure if the change cause this or not, I've edited a panel in Panel Studio and seen it change FS behavior from won't start to starts fine.:(

Share this post


Link to post
Share on other sites
Guest mgipson

There's a very good chance it is your gauge causing the crash :-)I would make sure that you are getting the DC for the correct element in your gauge. If you have a debugger it should be easy to find out where the problem is.

Share this post


Link to post
Share on other sites
Guest jcleland

Oh, I'm positive it's my gauge :) I just can't seem to attach to the fs9 process or the tmpxxxx process that seems to be a child. I've tried starting fs9.exe as the debug executable for my gauge dll, but it complains that the debugger is running and exits (fs9 does).How do you launch or attach to fs9 to debug your gauge? I'm using VS.NET2003 Enterprise.Thanks!

Share this post


Link to post
Share on other sites
Guest mgipson

The protection used to detect a debugger is the same used to look for CD number 4. Find yourself a no cd crack and then you will be able to debug using fs9.exe as the debug executable.

Share this post


Link to post
Share on other sites
Guest jcleland

I finally found a no CD crack for fs9.exe, but I have a problem debugging the gauge. I can set a breakpoint in the gauge during initialization when FS is loading and this stops fine. Unfortunately, this is not where I need to break. If I try to stop in the gauge code during rendering, etc, FS hangs as if it hit a BP, but I can't get the IDE to draw and I've forced to kill one of the processes. I'm guessing this is related to direct x and the fact that the app is full screen, but I'm not sure. Any ideas?

Share this post


Link to post
Share on other sites
Guest VulcanB2

Hi,I'm no expert, but try windowed mode??Could you get it to dump to a file the info that you need, like a trace log?Best regards,Vulcan.

Share this post


Link to post
Share on other sites
Guest jcleland

I did try that to no avail, but found a mutex to be at fault after all. This doesn't solve my gauge problem, but I did find myself able to debug it finally. It looks like it might be related to DLL relocation as I have an object allocated behind the scenes and a thread that calls it on a regular basis. The thread was created when the object was initialized and the data passed was the object's 'this pointer'. Every so often, the thread wakes up and calls (typecast)this->threadfunc(). Problem is, once I start a flight, a call to threadfunc() reveals an invalid instance pointer and all instance data is invalid. The address of the allocated block for the instance is correct and a destructor for the object was never called, so I'm assuming that the object's base address changed and the thread didn't know about it.The reason I did this was that I have no idea how often FS will call me for 'processing'. The gauge I'm writing needs to update its state in a time-sensitive manner, so a thread seemed like a good idea since the only call I know will come is a PRE_DRAW and I don't know how often that's called or if the interval is predictable.It's been a while since I ran into a DLL issue (like allocation/deletion of c++ objects from in/out side the library, etc), so I'll have to think on this one. Any insight on how I might handle time-sensitive processing in my gauge would be appreciated.Thanks for all the advice!

Share this post


Link to post
Share on other sites

PRE_DRAW is called once each FS frame, but only when the gauge is actually being drawn on the screen. PRE_UPDATE is called at a fixed rate of 18Hz, regardless of whether the gauge is visible or not.Doug

Share this post


Link to post
Share on other sites
Guest jcleland

I've ditched the threaded approach and handled my processing using PRE_UPDATE. I'm having problems drawing on my dc and having it show up. I load the DC from my STATIC image and draw directly on it like this: pBackground = (PELEMENT_STATIC_IMAGE)(pgauge->elements_list[0]->next_element[0]); if(pBackground) { HDC hdc = pBackground->hdc; drawsomething(hdc); SET_OFF_SCREEN(pBackground); }Just the background bitmap shows up, nothing that I've drawn over it.Does someone have a simple example of an owner drawn control that provides a background bitmap and draws on top of it using basic GDI?Thanks for all the help!

Share this post


Link to post
Share on other sites
Guest jcleland

I've made progress on this gauge, but I'm still having problems coming up with a workable solution for drawing on a static bitmap. Here's what I'm doing currently: I create two static images, one is a bezel for the gauge and the other is a bogus background that is empty:MAKE_STATIC( bezel, IDB_BEZEL, NULL, NULL, IMAGE_USE_TRANSPARENCY, 0, 0,0)PELEMENT_HEADER static_elements[] = { &bezel.header, NULL };MAKE_STATIC ( blankscreen, IDB_BLANK, static_elements, NULL, IMAGE_CREATE_DIBSECTION, 0, 0,0 )PELEMENT_HEADER render_list = &blankscreen.header;The first MAKE_STATIC is the gauge bezel and has a transparent center where the digital screen will go. It's like a picture frame. This draws correctly (transparent in the middle) if I use only one static image and just draw it by itself on the panel. In my callback, I do this: case PANEL_SERVICE_PRE_UPDATE: if(++updateCount > 17) { gauge_process(); updateCount = 0; bezel = (PELEMENT_STATIC_IMAGE) (pgauge->elements_list[0]->next_element[0]); screen = (PELEMENT_STATIC_IMAGE) (pgauge->elements_list[0]); if(bezel&&screen) { HDC hdc = screen->hdc; PIXPOINT dim = bezel->image_data.final->dim; int result = gauge_draw(hdc, dim.x, dim.y); SHOW_IMAGE(screen); SET_OFF_SCREEN(bezel); } } break;I need the gauge to redraw itself once per second. In case it's not obvious, I'm trying to always overlay the static bezel on top of the blank image. I'm trying to first draw on the blank STATIC using my gauge. Inside the gauge_draw() function, I'm creating a DC compatible to the hdc arg, loading a bitmap resource that's linked to the DLL and selecting it into the new DC. This image represents the digital screen. I then draw 'pixels' on the screen and, finally, StretchBlt it to the DC passed to the function using the x and y dims, intending to overwrite the MAKE_STATIC blank image with an image that consists of a bitmap that's drawn on.What shows up in FS is the screen image, then one that apparently drew on, looking the same as the original image loaded in MAKE_STATIC, as if the StretchBlt() failed, although it didn't.Sorry to be long winded, but I'm losing hope here. Any help is appreciated. Am I going about this the wrong way?Thanks

Share this post


Link to post
Share on other sites

"Sorry to be long winded, but I'm losing hope here. Any helpis appreciated. Am I going about this the wrong way?"Since it doesn't work, apparently so... ;)You can draw directly ON a bitmap, and don't really need a transparent background. Also, if you wish to overlay a final "frame" as the last draw element, it is much simpler to use the MAKE_SLIDER macro rather than another MAKE_STATIC element, although it is possible that way as well.Here's the way I draw the elements in such a gauge:////////////////////////////////////////Used to mask drawing when power OFF!MAKE_SLIDER(vision_Slider3,BMP_VT_BG,NULL,NULL,IMAGE_USE_ERASE | IMAGE_USE_TRANSPARENCY | BIT7,0,0,0,MODULE_VAR_NONE,vision_callback3,0,MODULE_VAR_NONE,vision_callbackS3,0)PELEMENT_HEADER vision_ElementList2[] = {&vision_Slider3.header,NULL};//Bezel only; transparent center, allows drawing surface to be seen!MAKE_SLIDER(vision_Slider2,BMP_VT_COVER,&vision_ElementList2,NULL,IMAGE_USE_ERASE | IMAGE_USE_TRANSPARENCY | BIT7,0,0,0,MODULE_VAR_NONE,vision_callback2,0,MODULE_VAR_NONE,vision_callbackS2,0)PELEMENT_HEADER vision_ElementList3[] = {&vision_Slider2.header,NULL};MAKE_STATIC( vision_image, BMP_VT_LM, //GDI+ drawing surface &vision_ElementList3, NULL, IMAGE_USE_ERASE|IMAGE_USE_BRIGHT|IMAGE_CREATE_DIBSECTION, 0, MAP_LEFT_BORDER,MAP_TOP_BORDER)PELEMENT_HEADER vision_next[] = { &vision_image.header, NULL };MAKE_STATIC( vision_background, BMP_VT_BG, //background image vision_next, NULL, IMAGE_USE_TRANSPARENCY, 0, 0,0)PELEMENT_HEADER vision_list = &vision_background.header;//////////////////////////////////////In my case PANEL_SERVICE_PRE_DRAW: section, I use a copy of the drawing surface to 'erase' the previous cycle's drawing, and prepare the surface for a fresh draw: Image image(L"AircraftMy Secret Aircrafttexturevision.bmp"); Rect destinationRect(0, 0, 600 * dx, 590 * dy); graphics.DrawImage(ℑ,destinationRect,0, 0, 600, 590, UnitPixel);Background Image / Gauge "OFF" coverhttp://img336.imageshack.us/img336/6015/vision9hr.th.pngDrawing Surface (DIBSECTION)visionlightmask3lc.th.png"Frame/Bezel with transparent screen"visioncover4km.th.pngThe final product...http://img495.imageshack.us/img495/5229/li...ontech011uv.jpg


Fr. Bill    

AOPA Member: 07141481 AARP Member: 3209010556


     Avsim Board of Directors | Avsim Forums Moderator

Share this post


Link to post
Share on other sites
Guest iholrf

Scary, but I actually understood all of that.CheersShad

Share this post


Link to post
Share on other sites
Guest jcleland

Do you use SET_OFF_SCREEN() or SHOW_IMAGE() when you finish drawing? What's the difference?Also, I've tried using PRE_DRAW, but it seemed like there were times where this wasn't being called very often, so I started using PRE_UPDATE and counting 1/18ths of second. Should PANEL_SERVICE_PRE_DRAW be sent to your callback on a regular basis (ie: meaning should you expect it constantly, not necessarily at a particular interval)Thanks

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Tom Allensworth,
    Founder of AVSIM Online


  • Flight Simulation's Premier Resource!

    AVSIM is a free service to the flight simulation community. AVSIM is staffed completely by volunteers and all funds donated to AVSIM go directly back to supporting the community. Your donation here helps to pay our bandwidth costs, emergency funding, and other general costs that crop up from time to time. Thank you for your support!

    Click here for more information and to see all donations year to date.
×
×
  • Create New...