Link to home
Start Free TrialLog in
Avatar of jabes012399
jabes012399

asked on

filling a dc manually

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 ?

}
Avatar of nietod
nietod

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.
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.
Avatar of jabes012399

ASKER


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      
 

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.
Adjusted points from 93 to 200

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

>> 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....
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
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.
I think you can memcpy in directdraw ,either



ASKER CERTIFIED SOLUTION
Avatar of nils pipenbrinck
nils pipenbrinck

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
btw.. forget about the german comment in the code.. it's not valid anymore.. I just forgot to delete it.
nils, I already suggested using the windows API.  He rejected that!
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
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

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"
jabes, what is happening to this question?
nietod -

collect your points.

i posted a question

entitled :

points for nietod

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?