|
The OP was setting WS_EX_LAYOUT_RTL on a (to be created) window in PreCreateWindow , but he had some (unstated) issue with it - which is why I asked him to describe what he was expecting vs what he saw.
|
|
|
|
|
Thanks for your reply.
Of one Essence is the human race
thus has Creation put the base
One Limb impacted is sufficient
For all Others to feel the Mace
(Saadi )
|
|
|
|
|
Hello guys!
Im new in C++ programing, and I want to
get and put same data in my COM.
I dont have problems with basic data types.
My IDL:
[propget, id(FW_DISPID_OFFSET), helpstring("property Offset")] HRESULT Offset([out, retval] short *pVal);
[propput, id(FW_DISPID_OFFSET), helpstring("property Offset")] HRESULT Offset([in] short newVal);
My Cpp:
STDMETHODIMP CYslider::get_Offset(short *pVal)
{
*pVal = m_Offset;
return S_OK;
}
STDMETHODIMP CYslider::put_Offset(short newVal)
{
m_Offset = newVal;
SetDirty(TRUE);
FireViewChange();
return S_OK;
}
So far so good , but now I dont know how to deal with arrays,
I googled a lot and I have found that solution is with VARIANT and safearray
but I dont know how to fill STDMETHODIMP for array.
My IDL:
[propget, id(FW_DISPID_ARRAYTEST), helpstring("property ArrayTest")] HRESULT ArrayTest([out, retval] VARIANT *pVal);
[propput, id(FW_DISPID_ARRAYTEST), helpstring("property ArrayTest")] HRESULT ArrayTest([in] VARIANT newVal);
My Cpp:
STDMETHODIMP CYslider::get_ArrayTest(VARIANT *pVal)
{
????????????????????????????????
return S_OK;
}
STDMETHODIMP CYslider::put_ArrayTest(VARIANT newVal)
{
????????????????????????????????
return S_OK;
}
I will be very happy if somebody could help me, with example, advice...
Bye,
Komofilms
|
|
|
|
|
I haven't worked with COM in quite a few months. The sample code below demonstrates everything you need to know based on your inquiry/statements.
STDMETHODIMP CYslider::get_ArrayTest(VARIANT v)
{
SAFEARRAY *pArrayVal = v.parray;
char HUGEP *pArray = NULL;
HRESULT hr = SafeArrayAccessData(pArrayVal,(void HUGEP * FAR *)&pArray );
SafeArrayUnaccessData(pArrayVal);
return S_OK;
}
HRESULT CYslider::put_ArrayTest(BYTE* data, LONG iLen)
{
VARIANT v;
SAFEARRAY *pArrayVal = NULL;
SAFEARRAYBOUND arrayBound;
CHAR HUGEP *pArray = NULL;
arrayBound.lLbound = 0;
arrayBound.cElements = iLen;
pArrayVal = SafeArrayCreate(VT_UI1, 1, &arrayBound);
if (NULL != pArrayVal)
{
HRESULT hr = SafeArrayAccessData(pArrayVal,(void HUGEP * FAR *)&pArray);
if (SUCCEEDED(hr))
{
memcpy(pArray, data, arrayBound.cElements);
V_VT(&v) = VT_ARRAY | VT_UI1;
V_ARRAY(&v) = pArrayVal;
}
else
{
if (NULL != pArrayVal)
{
SafeArrayDestroy(pArrayVal);
return S_FALSE;
}
}
hr = SUCCEEDED(get_ArrayTest(&v));
SafeArrayUnaccessData(pArrayVal);
}
VariantClear(&v);
return S_OK;
}
Hopefully its enough to get you started. You can tweak it so it works with your application. If you have any questions feel free to ask.
Best Wishes,
-David Delaune
|
|
|
|
|
Here's an example of creating a SAFEARRAY of doubles and returning it through an output parameter (as you have in your get_ArrayTest method):
SAFEARRAYBOUND saBound[2] = { {10, 0}, {5, 0} };
pSA = ::SafeArrayCreate(VT_R8, 2, saBound);
for(int i=0;i<10;++i)
{
for(int j=0;j<5;++j)
{
static long indices[2];
indices[0] = i;
indices[1] = j;
double value = i *5 + j;
::SafeArrayPutElement(pSA, indices, (void*)&value);
}
}
pVal->vt = VT_ARRAY|VT_R8;
V_ARRAY(pVal) = pSA;
Accessing a SAFEARRAY is similar - you use SafeArrayGetElement rather than SafeArrayPutElement and don't need to create or destroy the array.
The vt member of the VARIANT holding the array should define the type of the array as shown, with a VT_type defining the element type, ORed with VT_ARRAY . SafeArrayGetVartype interrogates the SAFEARRAY to get the element type directly.
HTH!!!
|
|
|
|
|
I made it this way....
STDMETHODIMP CYslider::put_VrednostArray(VARIANT newVal)
{
if (!(newVal.vt & VT_ARRAY)) return S_OK;
if (newVal.parray == NULL) return S_OK;
VARTYPE vt = newVal.vt & VT_TYPEMASK;
SAFEARRAY* psaSafeArray = newVal.parray;
SafeArrayLock(psaSafeArray);
long j;
long LBound, HBound;
unsigned long elementsToWrite;
int writeBufferCn;
LBound = psaSafeArray->rgsabound[0].lLbound;
//write minimum of: TotElements, array size
elementsToWrite = m_TotElements;
if (elementsToWrite > 10) { //psaSafeArray->rgsabound[0].cElements) {
elementsToWrite = psaSafeArray->rgsabound[0].cElements;
}
HBound = LBound + elementsToWrite;
VARIANT varValToWriteTableElement;
V_VT(&varValToWriteTableElement) = vt;
writeBufferCn =0;
for(j = LBound; j < HBound; j++)
{
switch( vt )
{
case VT_R4:
SafeArrayGetElement(psaSafeArray, &j, &V_R4(&varValToWriteTableElement));
m_VrednostArray[writeBufferCn++] =(varValToWriteTableElement.fltVal);
break;
default:
break;
}
}
SafeArrayUnlock(psaSafeArray);
FireViewChange();
return S_OK;
}
It Works
Thanks all for help!
|
|
|
|
|
Suppose I've got a variable of type BYTE. It looks something like 10001011 in the memory. Now I want to inverse it so that I get 11010001.
Thank you masters!
|
|
|
|
|
BYTE b = 139;
b = ((b * 0x0802LU & 0x22110LU) | (b * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16;
Credit for the discovery of this little neat trick goes to Sean Anderson at stanford university.
Best Wishes,
-David Delaune
|
|
|
|
|
Ok, now explain it
|
|
|
|
|
It works by masking bits/using the AND operator to get the bits in the proper location. It is very beautiful, you can see it working here:
DWORD iTmp =0;
BYTE b = 139;
DWORD c = (b * 0x0802LU);
c &= 0x22110LU;
DWORD d = (b * 0x8020LU);
d &= 0x88440LU;
iTmp = (c | d);
iTmp = iTmp * 0x10101LU;
iTmp >>= 16;
b = iTmp;
Best Wishes,
-David Delaune
|
|
|
|
|
definitely marvelous... with your accordance, may I quote you in my article which talks about bits twiddling ?
|
|
|
|
|
toxcct wrote: may I quote you
Hi toxcct,
Absolutely.
Best Wishes,
-David Delaune
|
|
|
|
|
shame on me, it was already (partially) there
check the article[^], at the Links chapter (down the end) ^^
there it is in the "Reversing bit sequences" chapter of this page[^]...
|
|
|
|
|
Hi,
That is an excellent link to an awesome collection of bit manipulation codes. I have used many of them in various projects over the years.
Best Wishes,
-David Delaune
|
|
|
|
|
|
Inefficient, sure, but maybe easier to grasp.
BYTE b = 139;
BYTE r = 0;
for (int i=0; i<8; i++)
{
r = r << 1;
r |= b & 0x1;
b = b >> 1;
}
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
I'm not sure it's much less efficient - all those multiplies will quite a high cost.
If it's just a BYTE, you could cut it down more by not even bothering with a loop:
BYTE b = 139;
BYTE r;
r = ((b & 1) << 7) | ((b & 2) << 5) | ((b & 4) << 3) | ((b & 8) << 1) | ((b & 16) >> 1) | ((b & 32) >> 3) | ((b & 64) << 5) | ((b & 128) >> 7) )
This would not extend well for unsigned __int64 ...
Iain.
Codeproject MVP for C++, I can't believe it's for my lounge posts...
|
|
|
|
|
Uhm...loop unrolling: the oldie-goldie game-hacker Iain!
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
Your version should be slightly faster. In theory on the Pentium 4 instruction cycle count should be as follows:
Bit masking technique:
3 MUL * 16 cycles
1 OR * 0.5 cycle
2 AND * 0.5 cycle
1 SHR * 4 cycles
===============
53.5 cycles
Your unrolled shifting:
8 AND * 0.5 cycles
7 OR * 0.5 cycles
5 SHL * 4 cycles
3 SHR * 4 cycles
================
39.5
It would be interesting to have MSVC output an .asm file with the /FA option. It would be interesting to see what the 2005/2008 compiler optimizer does to all of our codes!
Best Wishes,
-David Delaune
|
|
|
|
|
I think you may drop off a pair of AND s in Iain expression.
BTW: very good job, I like soo much your posts.
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
Hi,
if you need it once, the answers given to you are fine.
if you need to bit-swap an entire file or large memory buffer, I suggest you create a 256-byte lookup table, which you initialize by running one of the given code snippets for all possible byte values.
|
|
|
|
|
hi, everyone
recently I started a new project which needs to be written in plain C,
and I got problem with different compilers that:
I want the declaration of public APIs along with data types required to
be in some separate files, and the definition of the types in some others,
for example:
interface.h
struct _VECTOR;
/**
* there's a problem with the absence of 'struct' in function
* declaration at least in mingw2.95, but that's not the point
* of my post.
*/
void _InitVector(struct _VECTOR* pVector);
implementation.h
#include "interface.h"
/* my point is here */
typedef struct _tagVECTOR {
int a;
} _VECTOR, *_PVECTOR;
implementation.c
#include "implementation.h"
void _InitVector(struct _VECTOR* pVector)
{
pVector->a = 1; /* derefferencing pointer to imcomplete type. */
}
It seems that the compiler cannot recognize the fact that _VECTOR is a typedef
name of the struct _tagVECTOR;
By the definition of 'typedef', I know that _VECTOR declared in "interface.h"
is exactly the same entity to that in "implementation.h", although it turned
out to be a typedef name of _tagVECTOR, but it won't compile in mingw2.95 with
the error mentioned in the code above.
Revised version can solve the problem:
typedef struct _VECTOR {
int a;
} *_PVECTOR;
But I want it to be consistent with the general idea, so I revised further:
typedef struct _VECTOR {
int a;
} _VECTOR, *_PVECTOR;
It compiled with no problem, but I'm not sure if I'm lucky enough with other
compilers holding the potential issue of "typedef redefinition".
Thanks in advance.
|
|
|
|
|
Why are you posting a plain C question in a C++ / MFC forum?
That said, I think you should write
void _InitVector(_VECTOR* pVector)
instead of
void _InitVector(struct _VECTOR* pVector)
There is sufficient light for those who desire to see, and there is sufficient darkness for those of a contrary disposition.
Blaise Pascal
|
|
|
|
|
hi,
The joke is that because I think C is a subset of C++.
And I got problem with the absence of that 'struct':
[Error] parse error before '*'
It seems the pre-declaration can never be sighted by the compiler(mingw2.95).
|
|
|
|
|
6Qing88 wrote: And I got problem with the absence of that 'struct
Sorry I didn't read your post carefully. The problem is that you declare _VECTOR as a struct first
struct _VECTOR;
void _InitVector(struct _VECTOR* pVector);
but as a typedef later
typedef struct _tagVECTOR {
int a;
} _VECTOR, *_PVECTOR;
You can't forward declare a typedef as a struct, because it is not a struct - it is a typedef. I think it is intended to be that way (i.e. it's not the compiler but the C language specs that require it).
You can try writing this at the header (I haven't tested it)
struct _tagVECTOR;
typedef struct _tagVECTOR _VECTOR;
void _InitVector(_VECTOR * pVector);
There is sufficient light for those who desire to see, and there is sufficient darkness for those of a contrary disposition.
Blaise Pascal
|
|
|
|