|
My knowledge of the low level implementation of C++ structures and classes is limited.
But I want to ask someone who might know, is it theoretically possible to derive a class from a Win32 structure and add methods and still be able to pass the new "structure" to a Win32 API?
I do know that adding class data members would be out of the question, because that would change the size of the structure.
But is adding methods to a structure something I could do and still use it in the windows api?
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
Yes, it is very much possible. You can write something like this:
class MyPen : public LOGPEN {
public:
MyPen ();
void use_pen ();
private:
int stuff;
}
MyPen the_pen;
HPEN hp = CreatePenIndirect ((LOGPEN*)&the_pen);
Note that you can also extend your object with additional data members. They will be placed after the base class (Windows structure) and they will do no harm.
Mircea
|
|
|
|
|
Thanks for your reply. I'm excited to try this.
Your example is great. But if I wanted to use an array of MyPen's then that would surely cause problems because of the larger size, no?
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
Correct but only if the Windows API call takes an array of (the smaller) structures as parameters. Of top of my head, I cannot think of one that does.
Mircea
|
|
|
|
|
This is the way some MFC classes are implemented:
typedef struct tagPOINT
{
LONG x;
LONG y;
} POINT, *PPOINT, NEAR *NPPOINT, FAR *LPPOINT;
class CPoint :
public tagPOINT
{
...
};
No additional members and virtual functions to get binary compatibility with underlying structure.
|
|
|
|
|
Hi, thanks very much for your post.
Do I understand correctly that non-virtual functions would ruin binary compatibility?
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
Non-virtual functions don't change a class instance size. You can use this technique, as in existing Microsoft classes like CPoint, CRect, adding instance non-virtual functions and static functions, if necessary.
|
|
|
|
|
Hello,
I am displaying an image in a static control (in a dialog) and trying to stretch according to the zoom factor on mouse position. Zoom on mouse position is working fine, but the image is not fitting inside the static control, going all over the dialog.
Below is the code.
Gdiplus::Bitmap *gpBitmap = new Gdiplus::Bitmap(mImagePath);
int origW = gpBitmap->GetWidth(); int origH = gpBitmap->GetHeight();
RECT rcVPC;
GetClientRect(hWnd, &rcVPC); HDC hDc = GetDC(hWnd);
float perW = (float)rcVPC.right / (float)origW;
float perH = (float)rcVPC.bottom / (float)origH;
int newW = origW * perW * mVPZoomFactor; int newH = origH * perH * mVPZoomFactor;
Gdiplus::Bitmap *bmpResized = new Gdiplus::Bitmap(newW, newH, gpBitmap->GetPixelFormat());
Gdiplus::Graphics *graphics = new Gdiplus::Graphics(bmpResized);
graphics->DrawImage(gpBitmap, 0, 0, newW, newH);
int zoomWidth = (int)(0.5 + newW * mVPZoomFactor);
int zoomHeight = (int)(0.5 + newH * mVPZoomFactor);
double dXFactor = (double)rcVPC.right / stX; double dYFactor = (double)rcVPC.bottom / stY;
int left = stX - zoomWidth / dXFactor;
int right = stY - zoomHeight / dYFactor;
HBRUSH hB = GetSysColorBrush(COLOR_3DDKSHADOW);
FillRect(hDc, &rcVPC, hB);
HDC hdcMem = CreateCompatibleDC(hDc);
bmpResized->GetHBITMAP(0, &hBmpVPCanvas);
HBITMAP oldBmp = (HBITMAP)SelectObject(hdcMem, hBmpVPCanvas);
StretchBlt(hDc, left, right, zoomWidth, zoomHeight, hdcMem, 0, 0, newW, newH, SRCCOPY);
SelectObject(hdcMem, oldBmp);
DeleteDC(hdcMem);
delete gpBitmap;
Can anyone help me, what i am doing wrong?
Regards,
Gopinath.
|
|
|
|
|
Gopi Nath wrote: what i am doing wrong? Probably mixing GDI and GDI+; you should only use one of these, preferably GDI+. Zooming an image is quite simple in GDI+ as you just need to specify the target rectangle's position and size.
|
|
|
|
|
Thank you Richard, tried with GDI+ only with some changes, now, i am able to get the required output.
Regards,
Gopinath.
|
|
|
|
|
I'm working on an embedded ARM-project (STM32F) and I'm programming in C programming language and compiling with Eclipse/GCC. In the project there is TRACE functionality implemented that, if enabled, logs various things over UART using queues and DMA:
#define TRACE(grp, lvl, ...) traceToPrintStream(grp, __FILE__, __FUNCTION__, __LINE__, lvl, __VA_ARGS__) It can be used, e.g. like this:
TRACE("regCallbacks", T_D, "The user pressed the button");
TRACE("regCallbacks", T_D, "Write to reg %d. First written byte: 0x%X", regAddr, regValues[0]); I need a different trace that is not queued, does not use DMA and does not include the file name, function name and line number, but the other persons in this project do not agree to throw out the existing TRACE, so I need to make something in parallel. I want to be able to enable my TRACE in two ways, either by #defines:
#define ENABLE_USER_EVENTS_LOGGING
#define ENABLE_COMMUNICATOIN_BUS_LOGGING or by setting a varible during runtime:
Bool_t enableCommunicationBusLogging;
Bool_t enableUserEventsLogging; I need a different grouping (the grp parameter) than the others, so the example TRACEings above would have to be augmented with my grouping as well:
TRACE_EX("regCallbacks", USER_EVENTS, T_D, "The user pressed the button");
TRACE_EX("regCallbacks", COMMUNICATION_BUS, T_D, "Write to reg %d. First written byte: 0x%X", regAddr, regValues[0]); The rules I would like to apply are:
1. If my TRACE is enabled using the macros (hardcode enabled), then the other TRACE can not be used (hardcode disabled).
2. If my TRACE is not enabled using the macros, then both TRACEs can be enabled/disabled during runtime independently of each other. However, they are enabled per groups!
Does anybody know how I can solve this? I found a great website (C Preprocessor tricks, tips, and idioms · pfultz2/Cloak Wiki · GitHub[^]) that shows some really neat macro-tricks, but I'm not sure how to apply it my case.
|
|
|
|
|
As I understand it (assuming the traceToPrintStream function is fixed) you need a slightly different macro for your TRACE_EX, something like:
#define TRACE_EX(grp, lvl, ...) traceToPrintStream(grp, "", "", 0, lvl, __VA_ARGS__)
If you want to enable the traces at runtime then you need them always enabled at compile time, otherwise you will need to rebuild the code every time. So to allow the traces to be based on switches you need something like:
#define TRACE_EX(switch, grp, lvl, ...) \
if (switch) \
{ \
traceToPrintStream(grp, "", "", 0, lvl, __VA_ARGS) \
}
where switch is the name of the boolean that controls the tracing.
|
|
|
|
|
Ok, so this is what I have now:
#define USER_EVENTS_LOGGING 0x00000001
#define COMMUNICATOIN_BUS_LOGGING 0x00000002
uint32_t enabledMyGrpBitFlags = 0;
#if defined(ENABLE_USER_EVENTS_LOGGING)
#define TRACE_EX(grp, myGrp, lvl, ...) if (myGrp & USER_EVENTS_LOGGING) printf_(__VA_ARGS__)
#elif defined(ENABLE_COMMUNICATOIN_BUS_LOGGING)
#define TRACE_EX(grp, myGrp, lvl, ...) if (myGrp & COMMUNICATOIN_BUS_LOGGING) printf_(__VA_ARGS__)
#else
#define TRACE_EX(grp, myGrp, lvl, ...) \
do { \
if (myGrp & enabledMyGrpBitFlags) { \
printf_(__VA_ARGS__); \
} \
traceToPrintStream(grp, __FILE__, __FUNCTION__, __LINE__, lvl, __VA_ARGS__); \
} while (0)
#endif Is it possible to remove the run-time checks:
if (myGrp & USER_EVENTS_LOGGING)
if (myGrp & COMMUNICATOIN_BUS_LOGGING) so that the TRACE_EX macro would become empty when the myGrop isn't matching? In other words, let's say only ENABLE_USER_EVENTS_LOGGING (not ENABLE_COMMUNICATOIN_BUS_LOGGING) is defined, then I would like the following line to "disappear" after the preprocessor is finished:
TRACE_EX("regCallbacks", COMMUNICATION_BUS, T_D, "Write to reg %d. First written byte: 0x%X", regAddr, regValues[0]); Is that possible somehow?
|
|
|
|
|
The run time checks are only effective at the time the code runs, so there is no way that the macro can be changed at that point. And the macro itself is evaluated, and its code generated in the preprocessor, long before the code is running.
|
|
|
|
|
I want to be able to compile in 2 different modes:
1. Normal mode: The 2 types of TRACE can be enabled/disabled during runtime independently of each other.
2. Hardcoded my TRACE only mode: Only my TRACE is enabled (1 or more myGrp TRACE groups), it's impossible to enable/disable anything TRACE related during runtime.
So, when compiling in mode 2 above, it should be possible for the macro to evaluate the passed myGrp parameter to determine how the TRACE_EX should be expanded. So if we only enable
#define ENABLE_USER_EVENTS_LOGGING then the preprocessor should be able to determine that this line should be removed:
TRACE_EX("regCallbacks", COMMUNICATION_BUS, T_D, "Write to reg %d. First written byte: 0x%X", regAddr, regValues[0]);
|
|
|
|
|
I have tried what I think you are asking for but the preprocessor rejects it. As far as I know you can only do it the way I already suggested.
|
|
|
|
|
On the following webpage C Preprocessor tricks, tips, and idioms · pfultz2/Cloak Wiki · GitHub[^] it is shown how an IIF (immediate if) statement for macros can be implemented. But as soon as I pass an expression, as oppose to either 0 or 1, to it, I can't get it to compile either:
#define USER_EVENTS_LOGGING 0x00000001
#define COMMUNICATION_BUS_LOGGING 0x00000002
#if defined(ENABLE_USER_EVENTS_LOGGING) && defined(ENABLE_COMMUNICATION_BUS_LOGGING)
#define HARDCODE_ENABLED_MY_GRP_BIT_FLAGS (USER_EVENTS_LOGGING | COMMUNICATION_BUS_LOGGING)
#elif !defined(ENABLE_USER_EVENTS_LOGGING) && defined(ENABLE_COMMUNICATION_BUS_LOGGING)
#define HARDCODE_ENABLED_MY_GRP_BIT_FLAGS (COMMUNICATION_BUS_LOGGING)
#elif defined(ENABLE_USER_EVENTS_LOGGING) && !defined(ENABLE_COMMUNICATION_BUS_LOGGING)
#define HARDCODE_ENABLED_MY_GRP_BIT_FLAGS (USER_EVENTS_LOGGING)
#else
#define HARDCODE_ENABLED_MY_GRP_BIT_FLAGS (0)
#endif
IIF(1)(true, false) IIF((0 < (HARDCODE_ENABLED_MY_GRP_BIT_FLAGS & USER_EVENTS_LOGGING)))(true, false)
|
|
|
|
|
Sorry, that is something I have never seen before. To be honest I think you are in danger of making things far more difficult than you need. The original spec I suggested where you can generate (or not) the macro that includes a runtime check, is the simplest way of doing it.
|
|
|
|
|
Hi all,
Is there an easy way to save the current CMFCpropertyPage number when closing a CMFCPropertySheet so that it can be reopened on that page. It seems that this is not implemented by default.
|
|
|
|
|
Just save the active page index in registry before closing.
Then read it from registry before activating and set the active page.
|
|
|
|
|
Non-modal ActiveX Control, a self-draw CMyTreeCtrl is shown on it.
Now, I create a CMFCToolTipCtrl in my CMyTreeCtrl and I want to dynamically change the text color of Tooltip.
I use SetParams in the ToolTip callback function and set new color/text .
However, I can't get new color when the tooltip displayed.
After I debug and found that it can't enter CMFCToolTipCtrl onPaint. If I use invalidate, then the whole ActiveX Control will flash rapidly.
I inherited CMFCToolTipCtrl and found that WM_PAINT cannot be received in PreTranslateMessage.
It can only receive WM_TIMER. Any other functions in afxtooltipctrl.h are not entered when the tooltip is shown.
And CMyTreeCtrl can receive WM_PAINT.
Could you help me find the reasion? Thanks a lot.
|
|
|
|
|
Hi,
Are you creating the CMFCToolTipCtrl with the TTF_SUBCLASS flag[^]? If so then you should be able to capture the NM_CUSTOMDRAW message[^] and check for the CDDS_PREPAINT draw stage. You can use SetTextColor[^] to change the text color from there.
Best Wishes,
-David Delaune
|
|
|
|
|
Member 14882671 wrote: I use SetParams in the ToolTip callback function and set new color/text .
However, I can't get new color when the tooltip displayed.
After I debug and found that it can't enter CMFCToolTipCtrl onPaint. If I use invalidate, then the whole ActiveX Control will flash rapidly.
I inherited CMFCToolTipCtrl and found that WM_PAINT cannot be received
There are virtual methods you could use to customize CMFCToolTipCtrl:
CMFCToolTipCtrl Class | Microsoft Docs
and some other OnDraw... methods.
|
|
|
|
|
I have an old MFC Dialog Based app that was designed in the WinXP and Win7 era. This project is for internal use and no longer in development. In Win10, we have scaling issues with high DPI screens (some controls are small or positions compressed), which is to be expected. However, on standard DPI screens, there have not been any issues until now.
One user reports that the dialog window is correctly sized (fixed sized), but all the controls within the window are scaled up beyond the boundaries of the dialog window and so half the controls are hidden. Display scaling settings in windows is normal (100%). What could be causing this?
|
|
|
|
|
How hard could it be for Visual Studio (new or recent or even old versions for that matter) to convert this old MFC Dialog-based application?
If it could convert this old MFC Dialog-based application it will. If it can't then attempting to open it's project files will result in a telling error message which, of course, will be useful to the learned helpers here on CP.
Try posting that message.
|
|
|
|
|