Solved

filling a dc manually

Posted on 2000-04-18
19
380 Views
Last Modified: 2012-05-04
void CMainWindow::OnPaint()
{
      CPaintDC dc(this);
      char buf[8] = { 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF};

      CDC dcMem;
      dcMem.CreateCompatibleDC(&dc);

      dc.BitBlt( 10,10,10,10, &buf, 0, 0, SRCCOPY);

// how would i get above call to work properly ?
// is there a way to fill a dc manually ?

}
0
Comment
Question by:jabes012399
  • 9
  • 5
  • 3
  • +1
19 Comments
 
LVL 22

Expert Comment

by:nietod
Comment Utility
I don't know what you mean by "fill a dc manually"

but if you want to BitBlt a bitmap into an image, you have to create a source bitmap and select it into a source DC and then BitBlt () the source bitmap into the DC.

example follows.
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
Here is a prepared answer
****************************
You can copy a bitmap, or a portion of a bitmap between two compaible DC's using BitBlt.  So to copy a bitmap to the screen you need to create a DC that is compatible with the screen and copy the source bitmap from it to the screen.

First you need to have a Source DC, this is a memory DC for the source bitmap, that is the image to be copied to the display.  This DC must be compatible with the source bitmap and (since the source bitmap is compatible with the display) also compatible with the display.  You can use

HDC SrcDC = CreateCompatibleDC(DspDC);

to create a memory DC (SrcDC) that is compatible with the display DC (DspDC).  (The display DC may be a window's DC or a DC for the screen (display) obtaned with CreateDC().)

Next you need to select the source bitmap into the source DC.  Now this works like selecting any other tool, you must save the previous tool so you can select it back in before the DC is returned to the OS.  So you would do

HBITMAP OldSrcBmp = SelectObject(SrcDC,SrcBmp);

Now the memory DC contains the bitmap to be copied.  You can copy the source DC's image to the destination DC using BitBlt().

Next you need to clean up.  You do this by selecting the original bitmap back into the memory DC and then deleting the DC.  Like

SelectObject(SrcDC,OldSrcBmp);
DeleteDC(ScrDC);
*************************
That does not uise MFC, but the changes needed to use MFC should be obvious.  Let me know if you have any questions.
0
 

Author Comment

by:jabes012399
Comment Utility

i was hoping for a simpler answer
possibly along these lines:

void CMainWindow::OnPaint()
 {
 CPaintDC dc(this);
char buf[8] = {... some data ..};

 CDC dcMem;
 dcMem.CreateCompatibleDC(&dc);

memcpy( dc, buf, 8 );

dc.BitBlt( 10,10,10,10, &dc, 0, 0, SRCCOPY);

}

this is what i mean by manually.
i would like to poke values into the dc
via memcpy or another simple call      
 

0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
Well you can do that. You need to know a lot of unpublished information about the formats of bitmaps, DCs etc.  You probably will need to use verious tehcniques to get access to protected memory (forget that in NT) etc..

In the end (many months) you might have a solution that works just as well as what windows has provided for you.

Is there some reason you don't want to do this the "accepted" way.
0
 

Author Comment

by:jabes012399
Comment Utility
Adjusted points from 93 to 200
0
 

Author Comment

by:jabes012399
Comment Utility

well, i'm trying to avoid many months of trying to do it the  "accepted" way

seem's to me it would be a lot simpler to:

1) allocate memory for data.
2) fill data.
3) copy data to screen(application window).

i've visited code guru and all the bitmap stuff
is overwhelming.

i find your explanation regarding bitmaps and dc's confusing as well

i am rejecting your answer in hopes someone
has found a way around the "accepted" way.

more info:

i will be filling the data with unsigned char
hex values to produce a black and white image
0xFF = eight white pixels
0x00 = eight black pixels
0xAA = alternating black and white pixels

0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
>> 3) copy data to screen(application window).
Where are you going to copy it to?  the destination might be in RAM, but if so won't be in your address space.  More likely it isn't even in RAM.  i could be video memory on a video adapter card, that means the data has to be sent across the bus.  it could be memory in a printer, that means the data has to be sent out a com port, it could be....

how what format do you want to copy it to?  The format depends on the device and its manufacturer and its driver.  How do you know what forma to use?

>> i'm trying to avoid many months of
>> trying to do it the  "accepted" way
It shouldn't tke months.  Trying to do it yourself will be somewhere between nearly impossible and impossible.  The OS not only doesn't make it easy, it trieds to make it impossible.  If you don't have the expertiose to copy a bitmap to a DC, I doubt you can break windows NT security in a reliable way.  And if you do succeed, what happens when the security changes, a new device driver is developend a new piece of hardware is used etc etc etc.   All those months or years of work will be wasted.

>>  am rejecting your answer in hopes someone
>> has found a way around the "accepted" way.
There are plenty of alternatives, I just suggested the only reasonable one.

But you could use DOS instead of windows.  You could write your own GUI to be sued from DOS.   Or you could use DirectDraw which would really have no advantage over the API, it certainly isn't simpler.

>>  will be filling the data with unsigned char
>> hex values to produce a black and white image
>> 0xFF = eight white pixels
>> 0x00 = eight black pixels
>> 0xAA = alternating black and white pixels
That is easy enough to do with the windows API.

You create a monochrom bitmap with CreateBitmap() using a pointer to a data buffer that contains these values for the pixels.  Then you select that bitmap into a memory DC and BitBlt() it to the screen.   Were are talking about maybe 10 API calls and 10 minutes of programming and 20 minutes of debugging.  Or you can rewrite windows....
0
 

Expert Comment

by:teerawatw
Comment Utility
IMHO
Why don't you use CDC::SetPixel Funcion ?
You can paint dc manually but must write a little code than memcpy() which i think you can not do it because DC prevent us from direct access to Video memory like Dos you have to do the DC's way and if you use this solution you have to be sure about color value you will paint on that pixel

or if you do want to take it manually you can use directx the directdraw object allow us to write to vram directly ( direct is the key for DirectX ;)

twt
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
SetPixel() is fine for setting a very small number of pixels.  When setting large numbers of pixels the overhead is tremendous.  (like by more than 2 orders of magnitude.  i.e a BitBlt() that takes 1/10th of a second would take more than 10 seconds with SetPixel().  If you want to use an algorithm that sets individual pixels, you can use directdraw,  That will be substrancially faster than SetPixel(), but still much slower than setting them al at once.
0
Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 

Expert Comment

by:teerawatw
Comment Utility
I think you can memcpy in directdraw ,either



0
 
LVL 4

Accepted Solution

by:
nils pipenbrinck earned 200 total points
Comment Utility
ok.. a simple way to display graphics using win32 api is to create a dib and use the gdi functions to blit the stuff.

Here is a code I used some while ago (I'm now using ddraw, but it still works, and it's not that slow as you might expect it to be).


first I create a BitmapInfoHeader structure which describes my virtual bitmap: I use a 24 Bit per pixel truecolor bitmap because it can be converted fast to any other bitdepth.

Please take a look at the biHeight member. I'm passing a negative value to it. This is a trick which tells gdi that my bitmap is a topdown bitmap (e.g. the first pixel is the upper left, not the lower left). That made it easier for me to calculate the pixels.. (you can change that if you want..)

BITMAPINFOHEADER * bitmapinfo

    int bisize = sizeof( BITMAPINFOHEADER );
    bitmapinfo = (BITMAPINFO *)malloc( bisize + 12 );
    ZeroMemory( &bitmapinfo->bmiHeader, bisize );

    // BitmapInfoHeader eines normalen 16 Bit Bitmaps
    // wie wir es brauchen erzeugen
    bitmapinfo->bmiHeader.biSize        = bisize;
    bitmapinfo->bmiHeader.biWidth       = 256;
    bitmapinfo->bmiHeader.biHeight      = -256;
    bitmapinfo->bmiHeader.biPlanes      = 1;
    bitmapinfo->bmiHeader.biBitCount    = 24;
    bitmapinfo->bmiHeader.biCompression = BI_BITFIELDS;
    *((long*) bitmapinfo->bmiColors +0) = 0x0FF0000;
    *((long*) bitmapinfo->bmiColors +1) = 0x00FF00;
    *((long*) bitmapinfo->bmiColors +2) = 0x00FF;


Now as you created your bitmapinfoheader you can create a virtual buffer which holds the pixels of yuor bitmap. I used a 256x256 bitmap, but you can of cause change that to your needs:

unsigned char * buffer = new unsigned char [256*256*3];

fill a funny pattern into the bitmap.. here is the place where you can put anything in the buffer you want to:

// this code makes a blue scale going from left to right and filling the bitmap with a black to blue gradient.

for (int i=0; i<256*256*3; i++)
  buffer[i] =  (i&255);

Now - as you prepared your bitmap you can wait until you are in your Paint message handler.

If you're there you can simply call SetDiBitsToDevice or StrechDiBits to display the dib.

Here i fill the entire client window of the screen with the bitmap:


RECT r;
HDC Dc; // the dc must be requested from win32.. I don't know how this  works under mfc, but I'm sure you'll know how to get it...
GetClientRect( WindowHandle, &r );
StretchDIBits( Dc, 0, 0, r.right, r.bottom, 0, 0,256, 256, (void *) buffer ,bitmapinfo, DIB_RGB_COLORS, SRCCOPY );

That's all I think.. Hope it helps.

btw. you can reuse the buffer and the BitmapInfoHeader as often as you want.. Whenever you changed your buffer content make sure that the window will be repainted.

Hope this helps,

  NIls Pipenbrínck

 


0
 
LVL 4

Expert Comment

by:nils pipenbrinck
Comment Utility
btw.. forget about the german comment in the code.. it's not valid anymore.. I just forgot to delete it.
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
nils, I already suggested using the windows API.  He rejected that!
0
 
LVL 4

Expert Comment

by:nils pipenbrinck
Comment Utility
nietod.

Hm.. sounds funny.. how else should he access pixels on the screen in a compatible way?

I think one could hack itself into the gdi, but this is incompatible and I don't think it'll be any bit faster..

Nils
0
 

Author Comment

by:jabes012399
Comment Utility
nils -

thanks for code but could not get it to go.


nietod -

i figured it out finally.
following your advice.
2 days is better than 2 months.
how do you get your points now ?

actually i'd like to split the points with you and nils
since he was nice enough to send some code
and enthusiasm.

how does one go about that ?
i don't want to step on anyone's toes . . . .


teerawatw  -  sorry. but setpixel painfully slow

0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
Actually, I did post code, only it is "annotated" to explain what it is doing.

As for splitting points--there is no feature for this.   Here is another preprepared answer on that
*******************
There is no way to split points between experts.   You must choose the expert that you feel contributed the most and ask them to submit an answer (if they have not).  

If you feel two or more experts really deserve the credit you have two choices.  

First, if you have sufficient points and are feeling very generous, you can ask one expert to submit an answer to the current question, then ask additional "Dummy" questions for the other expert(s) to answer.  

Second, you can post a request at the EE customer service topic are that the points for the question be reduced or that you be given additional points in order to ask "dummy" question(s) for the other expert(s).  This should only be done in extreme cases as the customer service people are quite busy.

If you do ask dummy questions, post a comment on this message to let the experts know to look for the questions.  Also be sure to include the expert's name in the question so that other expert know what the question is for.  i.e. give the question a title like "Points for XXXXXXX"
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
jabes, what is happening to this question?
0
 

Author Comment

by:jabes012399
Comment Utility
nietod -

collect your points.

i posted a question

entitled :

points for nietod

0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
I see it, I'll answer it if you thought my "work" here was worth it.

I am curious to know what is happenign with this question though.  What did you decide to do?
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Unlike C#, C++ doesn't have native support for sealing classes (so they cannot be sub-classed). At the cost of a virtual base class pointer it is possible to implement a pseudo sealing mechanism The trick is to virtually inherit from a base class…
In days of old, returning something by value from a function in C++ was necessarily avoided because it would, invariably, involve one or even two copies of the object being created and potentially costly calls to a copy-constructor and destructor. A…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now