|
Right, I did understand that part. But what isn't clear to me is the fact that if I would, e.g. drop NT4 support, would the application still work in NT4? Or will it just fail to run?
|
|
|
|
|
If you call a function that is not supported on NT4, your application will fail to start; typically with an entry point not found error (or something similar.)
If you use a structure that is extended for other versions of windows, generally the app will work on NT4, but that function may fail or exhibit odd behavior.
If you use constants that are not meant for NT4, some functions will fail, others will ignore the new constants.
Anyone who thinks he has a better idea of what's good for people than people do is a swine.
- P.J. O'Rourke
|
|
|
|
|
Okay, that's pretty clear. Thanks!
|
|
|
|
|
I am a novice at programming and am working my way through Feng Yuan's book "Windows Graphics Programming". It's great stuff and he includes extensive development of useful graphics classes that can be used in your programs.
Anyway, I'm curious as to why he doesn't use the reinterpret_cast operator in his code when converting pointers. Typically he does something like this:
<br />
GetDIBits(hDC, hBmp, 0, ddbinfo.bmHeight, NULL, (BITMAPINFO *) & dibinfo, DIB_RGB_COLORS);<br />
int nInfoSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * GetDIBColorCount(dibinfo.bmiHeader);<br />
int nTotalSize = nInfoSize + GetDIBPixelSize(dibinfo.bmiHeader);<br />
BYTE * pDIB = new BYTE[nTotalSize];<br />
if ( pDIB )<br />
{<br />
memcpy(pDIB, & dibinfo, nInfoSize);<br />
if ( ddbinfo.bmHeight != GetDIBits(hDC, hBmp, 0, ddbinfo.bmHeight, pDIB + nInfoSize, (BITMAPINFO *) pDIB, DIB_RGB_COLORS) )<br />
{<br />
delete [] pDIB;<br />
pDIB = NULL;<br />
}<br />
}<br />
ReleaseDC(NULL, hDC);<br />
return (BITMAPINFO *) pDIB;<br />
This is a segment from one of his functions that converts a Device Dependent Bitmap to a DIB (Device Independent Bitmap) which he will later save to file in the Bitmap format. The recasting of pointers is a critical technique to this operation, because when he makes a call later in his program to WriteFile he just supplies the pointer as the parameter.
Anyway, this is from the documantation at the MSDN site:
C/C++ Language Reference
reinterpret_cast Operator
reinterpret_cast < type-id > ( expression )
The reinterpret_cast operator allows any pointer to be converted into any other pointer type. It also allows any integral type to be converted into any pointer type and vice versa. Misuse of the reinterpret_cast operator can easily be unsafe. Unless the desired conversion is inherently low-level, you should use one of the other cast operators.
I's appreciate any enlightenment on the subject that you can provide, as pointer casting appears to be an operation that could possibly be corrupted. I'm thinking that a special operator could be designed that would be better suited to these types of code transitions.
|
|
|
|
|
As far as I know, reinterpret_cast isn't anything different from a class C-style cast. You can basically turn any pointer into anything else either way.
I'm not sure what you would want with this special operator? But you might want to take a look at dynamic_cast, that might be the one you're looking for. But that only works with polymorphism, and that doesn't work for the WINAPI stuff.
|
|
|
|
|
Thanks for the response. I should have been clearer in my initial question.
The code that Feng Yuan uses works perfectly, but appears cumbersome and even though the compiler will accept the cast, it does no checking of types to insure adequate memory addressing (...but, I'm probably wrong about this). In this case, Feng Yuan casts from a BYTE pointer to a BITMAPINFO pointer (they obviously are the same size or the function would not work). I have not tried this, but, I'm guessing that you could use the same technique with a VOID* (VOID pointer).
More importantly, why even use reinterpret_cast at all? Why does Microsoft even include it in it's Programmer API? This whole subject is a mystery to me. I'm curious as to what instructions the compiler actually issues when such a cast is made.
Also, an assert statement could be made, but Feng Yuan never does. No doubt I'm missing something important here.
This further information from MSDN:
There are several casting operators specific to the C++ language. These operators are intended to remove some of the ambiguity and danger inherent in old style C language casts. These operators are:
dynamic_cast Used for conversion of polymorphic types.
static_cast Used for conversion of nonpolymorphic types.
const_cast Used to remove the const, volatile, and __unaligned attributes.
reinterpret_cast Used for simple reinterpretation of bits.
|
|
|
|
|
I can't tell you as to why using reinterpret_cast instead of C-style casting. Basically it comes down to the same as far as I know, and you could use it for the sake of consistancy. Like if you use stuff like dynamic_cast, static_cast, etc. it would be more consistant to use reinterpret_cast as well.
Maybe this link can enlighten you more: http://www.informit.com/guides/content.asp?g=cplusplus&seqNum=131
|
|
|
|
|
According to Stroustrup[^], part of the reason for adding the various cast operators and making them so syntactically ugly was to make them more noticeable in your code. It's difficult to tell the difference between a 'C'-style cast and a user-defined conversion operator. The '*_cast' operators make those sorts of things easier to see, and more explicit of programmer intent.
Software Zen: delete this;
|
|
|
|
|
reinterpret_cast is the same as the C style cast your writer uses. The compiler does nothing, the cast is a statement from you the programmer that the types are equivalent. In this case they are. It would be better style to use reinterpret_cast but the code in question isn't modern C++, rather it's C with a few C++ bits, so the C style class seems appropriate.
The other C++ casts are more constraining and allow the compiler to determine whether what you (or a user of your code) are trying to do is appropriate.
Paul
|
|
|
|
|
Paul, thanks, that makes alot of sense. I appreciate the response.
I don't know why, but I've always had this irrational fear of rogue pointers, since it's so easy to re-assign the address. But, they sure are ubiquitous, and so many Windows functions couldn't live without them.
|
|
|
|
|
Hi there,
I have an image available as a pointer to an unsigned char array (grayscale, 1 byte/pixel) and I know its width and height.
I can add all data to a BITMAP structure, but how do I display that using MFC?
Thanks in advance!
|
|
|
|
|
If you have an HBITMAP returned from a function such as CreateDIBSection , you need to select that object into a device context compatible with the screen (call CreateCompatibleDC ) and use BitBlt to copy from the memory device context into the screen device context.
BitBlt also has a number of cousins for stretching the bitmap while copying, or performing mask or pattern operations.
Stability. What an interesting concept. -- Chris Maunder
|
|
|
|
|
Thanks for your answer.
I have used a library to deal with image calculations and have the pointer and the width and height available, so I can fill a BITMAP structure.
Other than that, I have a dialog to let the user input some data, so I need to open a new dialog, which I already did, but how do I move on?
Al
|
|
|
|
|
I have an SDI application.
This code in on the OnOpen document function.
for(i=0; i<numevents; i++)="" the="" numevents="" are="" midi="" events="" extracted
="" from="" document
="" {
="" event="pTrackList[0]-">GetEvent(i);
time = event->time;
status = event->status;
data1 = event->data1;
data2 = event->data2;
data3 = event->data3;
//temp = tempo(data1, data2, data3);
if(status == 144 && data2 > 0)
{
tempPoint = tempGrid->FindNote(data1);
tempPoint.y = -tempPoint.y;
tempPoint.x = cur_pos;
tempPoint.x = tempPoint.x * 720;
cur_pos++;
pView->AddNoteToptArray(tempPoint);
}
The Find Note function returns some coordinates. The AddNoteToptArray adds the tempPoint value to a CPoint array which is used to draw in the OnDraw Function. The problem is that the notes are drawn and then immediately cleared of the screen. Is that when the view is updated from the document..? Is the only way to make this work to use a document to hold all the data I need to draw the notes? Will it need to have virtual functions to draw them as well?I don't know much about document/view arctitecture so any kind of help could prove usefull!
|
|
|
|
|
Hi guys
Do you know a reason to get an error linking, but only in release mode.
In debug mode all is good, but in release I receive a linker error.
Do you know why this could happens?
Doc
|
|
|
|
|
More Info
I'm using class CListCtrlEx in the article about ScrollSync
This is what the class has
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
If I remove this, in debug mode I receive the same errors linking as release mode.
What I have to do to link in release mode?
Thanks
Doc
|
|
|
|
|
Have you perhaps tried to replace the global ::operator new ? What is the actual linker error message?
Stability. What an interesting concept. -- Chris Maunder
|
|
|
|
|
I'm using DAO (CDaoRecordset) on an Access database. I'm using Get/Set FieldValue using an ordinal position. In debug everything is fine. In release mode I get "Data Type Conversion" errors. It's happened on numeric and text fields - I know that the correct type/value is being get/set.
When I change the ordinal to an actual field name everything is fine.
|
|
|
|
|
Hi,
I'm using Dependency Walker 2.1.3790. It lists 5 types of dependencies: Implicit, Delay-load, Forward, Explicit, and System Hook. I want to know how they are related to the 2 types of Dynamic Linking: Load-time and run-time. Does the dependency type indicate which Dynamic Linking type is used?
Thank you for any help.
|
|
|
|
|
The simplest ones to explain are Implicit and Explicit. Implicit is where the binary's Import Address Table lists a particular function exported by a given binary (normally a DLL). This type of dependency is resolved by the loader when loading that binary and causes an error if not present. This is your 'load-time' case.
The Explicit case is where LoadLibrary has been used to load a DLL by the program or one of its DLLs. This can include loading COM DLLs (which you'll see grouped under OLE32.DLL, since that actually does the loading).
Forwarding is an advanced feature where a DLL can simply include a function in a different DLL in its exported function table. On Windows NT-based systems, some functions exported by kernel32.dll are simply forwarded on to ntdll.dll . This allows you to move functionality between DLLs without having to recompile the applications.
Delay-Load is another advanced feature which allows the application to get the benefit of run-time linking while having the convenience of simply calling the functions in code. If the function called is not present at run-time, a Windows SEH exception is raised. IIRC, this feature is used by MFC 6.0 and higher to reduce start-up time.
I'm not entirely sure how the System Hook type occurs.
Stability. What an interesting concept. -- Chris Maunder
|
|
|
|
|
I started on the below description and code and am trying to see if I can get any further. Does this look right?
lab.h
public class Point
{
friend ostream &operator<<(ostream&, const Point&);
friend istream &operator>>(istream&, Point&);
private:
double x;
double y;
String name;
public
Point();
Point(double a, double b);
Point(const Point& p);
//have to add methods to this class and add the operators +,-,++,--,<,>,==,=, operators
};
//I have to add 2 classes Rectangle and Oval
//Rectangle is to have a point included in it which represents the left corner of the
//Rectangle. It should also have a length and width data member
//create the correct methods and include a method named move which can have 2 forms
//from 1 move(Point p) which says move the current point to (x+p.x, y+p.y, form 2 is move
// (double x, double y) which says make the current point set to this.x,this.y
// have the values of x,y.
// Oval is to have a Point p which is its center and a radius and should also have a move
//which operates the same as the one in Rectangle.
public class Rectangle
{
friend ostream &operator<<(ostream&, const LPoint&);
friend ostream &operator>>(istream&, LPoint&);
private;
double l;
double w;
String name;
public; Move(Point p)
Move(double x, double y)
};
public class Oval
{
friend ostream &operator<<(ostream&, const CPoint&);
friend ostream &operator>>(istream&, CPoint&);
private;
double c;
double r;
String name;
public; Move(Point p)
Move(double x, double y)
};
does this look like it makes any sense?
Thanks
|
|
|
|
|
Hi.
I have a class, CMyClass, and I want to build an array of CMyClass.
Could I write something like this?.
i=0;<br />
CMyClass* myClass = new CMyClass[];<br />
myClass[i] = new CMyClass();
That throw the following error:
error C2582: 'CMyClass' : 'operator =' function is unavailable
I don't want to use some template array.
What I'm doing wrong.
Thank you.
|
|
|
|
|
Try:
CMyClass** myClass = new CMyClass[];
myClass[i] = new CMyClass();
John
|
|
|
|
|
Hi John.
Now throws:
error C2440: 'initializing' : cannot convert from 'class CMyClass *' to 'class CMyClass ** '<br />
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
I don't know what happend.
|
|
|
|
|
Sorry my fault:
CMyClass** myClass = new CMyClass*[NUMBER_TO_ALLOCATE];
myClass[i] = new CMyClass();
John
|
|
|
|
|