I need to keep track of a list of hDC's, However, I noticed taht every time I GetDC(), I need to ReleaseDC(). Otherwise I will get NULL.
The question is, should I store all the hDC's when I GetDC()? or I need to store hWnd and use GetDC() when I need a hDC?
Why do you even need to store hdc?
hdc are just pointers, so even if you store it, it gets changes or altered when ReleaseDC is called or any other DC operation is done..
I hope u understand how pointers work.
You need to ReleaseDC after every GetDC otherwise you wont get desired output.
Related
Could you explain me why WinAPI needs InvalidateRgn with its handle to the region to be added to the update region (hRgn) if we have only RECT during BeginPaint while processing WM_PAINT?
Thanks in advance!
Win32 API is about 30 years old; there's lots of code in there for backwards compatibility. There's a perfectly sane InvalidateRect.
Having said that, calling InvalidateRgn with bErase=TRUE will erase a non-rectangular area.
Requiring the specific (complex) update region is an extremely rare use case. The system is optimized for the most common use case, where applications invalidate and track dirty areas of a window using rectangles. That's what you get when calling BeginPaint.
If you are in the rare situation where you need the update region, you can call GetUpdateRgn instead. Since BeginPaint validates the update region, you would have to call GetUpdateRegion before that.
Why does Windows not just go ahead and invent a BeginPaintEx API that returns the update region? Because adding an API is unbelievably expensive, and needs to be well justified. Adding a function that doesn't add any value (as in this case) is hard to justify.
Okay, so now I want to create a COM interface that represents the data model my custom table control will take, instead of using messages passed between the table and its parent window. The table currently displays text, images, and checkboxes. Objects that implement the interface are expected to live in single-thread apartments.
I know I can use BSTRs for strings and some integer type for the checkbox booleans, and that there are already established conventions for ownership transfer for these that I can follow. But I'm not sure about bitmaps.
What I want to do is call the model object's GetCellData() method, which takes the row, column, and a pointer to a VARIANT that the model will put the cell's data in. I only need to draw the bitmap once before disposing of it. Since bitmaps can only be selected into one DC at a time, I need to be the exclusive owner of the bitmap, but only temporarily.
I tried looking for a similar COM interface by Microsoft that did this already, but didn't find anything (or didn't look using the right terms).
So my questions are:
How would I pass the HBITMAP into the VARIANT? My best guess is storing it in the byref field.
How should I negotiate ownership of the HBITMAP? I see two possibilities: either a) require a copy of the HBITMAP to be sent each time, with the table control itself calling DeleteObject(), or b) have the HBITMAP borrowed (use it and then have another model method FinishedWithBitmap() that will be called when finished). Is any one of these more suited to COM's rules than the other? Or do I have the wrong idea entirely? Would STGMEDIUM be appropriate?
I should point out the HBITMAPs are treated as 32-bit ARGB (that is, they're drawn by AlphaBlend()). I found IPicture but that doesn't seem appropriate for this format.
Thanks.
Update
Okay here's the general idea. Let's say model is the table model, which is the server. The table itself is the client. The code for drawing a bitmap cell in the client would look like this:
HBITMAP bitmap;
ITableModel_GetCellData(model, row, column, &bitmap);
// draw the bitmap (CreateCompatibleDC(), SelectObject(), AlphaBlend())
At this point the client doesn't need bitmap anymore. I'm asking if COM has a canonical way of defining the ownership of the HBITMAP to the client's drawing code, so I as the client author would know if I should either write
// the client owns the bitmap
DeleteObject(bitmap);
or
// the model still owns bitmap
// we need to explicitly give it back because only one DC can have a bitmap selected at one time
// since each client has the DCs, the server needs to know when it's safe to give the same HBITMAP to another client
ITableModel_ReturnBitmap(model, bitmap);
(IDataObject provides a solution to this problem in the form of STGMEDIUM.pUnkForRelease.)
In the end I decided to take a different approach for now: rather then returning an HBITMAP to draw, I provide a method that takes the HDC and have the model do the drawing. (The DLL will provide a helper implementation for people who do write custom models.) Other COM interfaces (like IImageList) do this already, so why not :/
I'm not sure if I'll keep the GetCellData() method as it is or break it apart into one function for each data type. Another column type I just realized I would need for the model is COLORREF (for customizing cell background colors; model columns and view columns are not equivalent). I'm also not sure what I'll do about a SetCellData() method in the same vein; it'll only be used by the Table view itself when the user decides to change something int he UI (by checking a checkbox, for instance) and I don't think I'll provide a way to change images directly from within the table, so... Adding separate model functions for each different data type would obviously be a poor idea (especially if interfaces have to remain constant once finalized), but VARIANT is looking less and less optimal.
That is certainly one way. The beauty of implementing IDataObject is that the consumer of the object can decide on what format he requires--of course you have to say what you will provide. But, with delay rendering, you can wait until they actually request the data before you provide it.
Can we store the the address of the Object in windows Registry and later from some other function read the address we've stored and make changes in that Object directly.
If it is possible, any pointers to getting started tutorial ..!
You could store the address of an object in the registry and then come back later, read it, and then modify the object. For example in C you could have a pointer, convert it to a long, and store it in the registry:
SomePointer *p;
long i = (long)p;
// now store i in the registry
And later, get it back:
int new_i = read value from registry
SomePointer *new_p = (SomePointer *)i;
You really don't want to do that, though.
First, that pointer is only valid for the current instance of the program. If you exit the program and restart, then the pointer is no good. In addition, the pointer will be meaningless to any other application that might be running at any time. Also, in a garbage collected environment that can move things around in memory, the pointer could become invalid at any time.
Also, there's a performance impact. Accessing the registry is very slow.
From a software construction standpoint, it's really bad form to use a global resource such as the registry to solve the local problem of sharing data in a single program.
And, finally, from a practical standpoint, it makes no sense. If you have access to the source code so that you can modify it to write and read the registry, then you can use a more robust and less intrusive way to share the data. For example, the module that writes the registry could instead just export a symbol, and the module that you would have had reading the registry can access that exported symbol.
So, yes ... it is possible to store a pointer in the registry, and later read it back and access the object to which the pointer refers. But it's a really bad idea.
When using libspotify, I respond to callbacks about playlists changing by going through the playlists and getting information about the tracks.
When I get a track handle, when does that track handle become invalid? Can I assume that in a session, a given value for a track handle will always refer to the same track? Do I need to increase and decrease the ref count of tracks manually to be sure?
Thanks
Tom
As per the docs:
Reference counting is used for all domain objects in libspotify. Functions including the string create will return an object with a pre-incremented reference count. Thus, each create must have a corresponding release when the value is no longer needed.
Other accessor functions (including sp_link_as_artist et al.), on the other hand, returns a reference borrowed from the object it was retrieved from. Retrieving an sp_album from an sp_link would make the album object survive until the link object is freed, unless its reference count is explicitly incremented.
So if you get a track handle by calling sp_playlist_track – which does not contain the string create – the track reference is owned by the playlist. You can only be sure it is still valid while you are sure the playlist handle is valid, and you are sure the playlist still contains the track, unless you manually increase its reference count.
Similarly, a playlist obtained from a playlist container can only live as long as the container, and might not live as long.
In practice, I think you should add a reference to the track before you return from the callback or call into sp_session_process_events again. It's fine to rely on the parent object keeping it alive before that point, but after that point it's much harder to reason about, so just add a reference and later release it when you're done.
I am writing some kind of IPC functionality and need to pass certain resources from one process to another. This works well for Pipe handles etc. which can be duplicated via DuplicateHandle. Now I need to pass a HDC from one process to the other. Is this even possible? If yes: how?
Sub-Question: I am assuming passing window handles (HWND) from one process to the other is safe. Is this assumption correct?
HWNDs can be shared between processes, SendMessage() wouldn't work otherwise. They are however scoped to a specific desktop, a desktop is associated with a session. There is one session for each logged-in user. And session 0 is special, the session in which services run. And there's a secure desktop, the one you see at login or when you press Ctrl+Alt+Del, you cannot mess with the password entry box. But as long as both processes run in the same desktop you won't have any trouble.
HDCs are murky, never tried that. I wouldn't recommend it. You can always create one from a HWND with GetDC().
All GDI handles are stored in a table that is mapped into every process. The entries in the table contain the process id of the owning process, and this is checked on every GDI access to the handle.
So, (ironically), GDI handles - including HDCs - are valid system wide. But can only be used from the process that created them.
This Page documents the process affinity of GDI objects. Of course, as a counter point it is worth noting that some COM functions, and window messages like WM_PRINT do not have any interprocess restrictions and they ARE passed HDC's, so they clearly have to do something behind the scenes to marshal the HDC from one process to the next.
Assuming, that you want to paint onto a HDC belonging to one process from another process (e.g. by using BitBlt) then as pointed out by nobugz and Chris Becke you cannot share that HDC across process boundaries. But, further assuming that the HDC of that one process belongs to a window (and your intention is to finally draw onto that window) then you can pass that window handle to the other process and in this process use GetDc to obtain a HDC. With this HDC you can then paint onto the window of the other process.