filling a dc manually

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

      CDC dcMem;

      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 ?

Question by:jabes012399
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 9
  • 5
  • 3
  • +1
LVL 22

Expert Comment

ID: 2727745
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.
LVL 22

Expert Comment

ID: 2727754
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

That does not uise MFC, but the changes needed to use MFC should be obvious.  Let me know if you have any questions.

Author Comment

ID: 2729136

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

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

 CDC dcMem;

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      

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

LVL 22

Expert Comment

ID: 2730226
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.

Author Comment

ID: 2731120
Adjusted points from 93 to 200

Author Comment

ID: 2731121

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

LVL 22

Expert Comment

ID: 2731330
>> 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....

Expert Comment

ID: 2733478
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 ;)

LVL 22

Expert Comment

ID: 2734133
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.

Expert Comment

ID: 2734208
I think you can memcpy in directdraw ,either


Accepted Solution

nils pipenbrinck earned 600 total points
ID: 2734211
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..)


    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:

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



Expert Comment

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

Expert Comment

ID: 2734235
nils, I already suggested using the windows API.  He rejected that!

Expert Comment

by:nils pipenbrinck
ID: 2734281

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..


Author Comment

ID: 2738290
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

LVL 22

Expert Comment

ID: 2742562
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"
LVL 22

Expert Comment

ID: 2759243
jabes, what is happening to this question?

Author Comment

ID: 2766040
nietod -

collect your points.

i posted a question

entitled :

points for nietod

LVL 22

Expert Comment

ID: 2768900
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?

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Errors will happen. It is a fact of life for the programmer. How and when errors are detected have a great impact on quality and cost of a product. It is better to detect errors at compile time, when possible and practical. Errors that make their wa…
C++ Properties One feature missing from standard C++ that you will find in many other Object Oriented Programming languages is something called a Property (http://www.experts-exchange.com/Programming/Languages/CPP/A_3912-Object-Properties-in-C.ht…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.
Suggested Courses

770 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