|
hfry wrote: This is correct. However attempting to send WM_KEYDOWN isn't any better.
If your needs aren't particularly complicated you can send WM_NOTIFY[^] notification message to the parent. You will be limited to this set of notifications though. If your needs are more complicated define your own custom notification notification message using #define UWM_MYCONTROLNOTIFY WM_APP + x or RegisterWindowMessage() whichever is appropriate for your application.
Well, just for make sure of this part.
I just take WM_KEYDOWN as a example (not a good one? ). Here you said 'isn't any better', is it because that I redirect the message to its parent directly w/o any processing. If I can use some user defined message, there has no problem on the design, it this right?
Jay Zhu@Shanghai, China
|
|
|
|
|
Jay Zhu wrote: I just take WM_KEYDOWN as a example (not a good one?).
Actually most of the WM_ messages would be bad to send to the parent. Exceptions would be notification messages eg WM_COMMAND/WM_NOTIFY.
Jay Zhu wrote: If I can use some user defined message, there has no problem on the design, it this right?
Yes this is correct. Take buttons for instance, they don't send WM_LBUTTONDOWN/WM_LBUTTONUP to the parent when clicked, they send a BN_CLICKED notification to the parent so the parent can know exactly what has happened.
|
|
|
|
|
I think i am not very clear about the difference between macro ON_MESSAGE and ON_NOTIFY, anyone who can give me a clear explaination?
It seemed very big, but you can give me any comment you remember.
|
|
|
|
|
JackNotAll wrote: I think i am not very clear about the difference between macro ON_MESSAGE and ON_NOTIFY, anyone who can give me a clear explaination?
ON_NOTIFY is used for handling a particular WM_NOTIFY message, such as LVN_* or TVN_* notifications sent by list view or tree view controls. ON_MESSAGE is used for handling any message that does not have a specialised ON_* macro such as an application-specific mesage.
Ryan "Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late" John Nichol "Point Of Impact"
|
|
|
|
|
Ryan Binns:
Thank you so much. I learn from your comment that ON_NOTIFY is used for WM_NOTIFY message, and ON_MESSAGE macro is used for application-specific message, usually a user defined message.
But i still have some questions. I modify an existed Grid Ctrl source code. And i found some WM_NOTIFY message. Because there are some different types cell in grid control, such as edit type, datetime type, and so on. so the existed code use the ON_NOTFY marco to implement these function.
I give your the source code
.h
afx_msg void OnEditCell(NMHDR* pNMHDR , LRESULT* lResult);
.cpp
ON_NOTIFY( CLVN_EDITCHANGE , IDC_LISTVIEWEDIT , OnEditCell)
void CPFGridListCtrl::OnEditCell(NMHDR* pNMHDR , LRESULT* lResult )
{
.......
}
CLVN_EDITCHANGE and IDC_LISTVIEWEDIT is defined by author.
My question is in this situation, why do he use the ON_NOTIFY macro?
And can i implement it by using ON_MESSAGE marcro? perhaps we can, i think i can response the WM_LBUTTONDOWN message and sendmessage in it. Can i implement it by such action?
and i think the question will focus on who send the message. You know, if we define a user message, and we will use SendMessage function to send the message, but if we use ON_NOTIFY, actually, i don't know who send the WM_NOTIFY message to system?
Best Regards
JackNotAll
|
|
|
|
|
JackNotAll wrote: why do he use the ON_NOTIFY macro?
WM_NOTIFY messages contain a sub-message type that indicates the specific type of WM_NOTIFY message that is being sent. In this example, he is handling a WM_NOTIFY message of type CLVN_EDITCHANGE. Since the base message is a WM_NOTIFY, he is using ON_NOTIFY() to handle it. You could use ON_MESSAGE() if you really wanted to, but it's not the best way to do it.
Ryan "Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late" John Nichol "Point Of Impact"
|
|
|
|
|
Ryan:
Thank you. I will research them further more.
Best Regards
jackNotAll
|
|
|
|
|
I want to display transparent controls on my dialog-based app.
Normally this is pretty easy: override WM_CTLCOLOR, set transparent background mode and return a hollow brush.
This works fine with all controls *except* checkboxes. For some reason the background of checkboxes will become black. This is very odd since this does not happen with other CButton variations (ie. standard buttons, radiobuttons).
Any suggestions?
|
|
|
|
|
did you use CTLCOLOR_STATIC for check-box?
|
|
|
|
|
No, I don't check the control type because all controls have to be transparent.
So normally the code below should work for checkboxes but it doesn't
HBRUSH CTest::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = (HBRUSH)GetStockObject(HOLLOW_BRUSH);
pDC->SetBkMode(TRANSPARENT);
return hbr;
}
|
|
|
|
|
I'm seeing the same problem. Checkboxes are drawing with a black fill colour when the brush is set to HOLLOW_BRUSH.
Was a solution ever found?
|
|
|
|
|
Hi,
I have written a VC++ 6.0 program to send data through the serial port.I
have successfully sent the ASCII characters using my code.But now I need to
send defined block of bits (eg. "1100110") through the serial port.Is it
possible. Also if there is any problem I can add some overhead bits and make
the number of bit to 8 so that it can be defined as a byte,
I will be really happy if someone of you can help me regarding the above
matter.For your conveience I have given below some parts (open port and
sending data) of the code that I am using.
//To open the port and Configure
HANDLE handlePort_; // the object that is a instace of port.
DCB config_1;
BOOL openPt(BOOL statusPort_1,const char* portName)
{
// Defaults
config_1.ByteSize = 8; // Byte of the Data.
config_1.StopBits = ONESTOPBIT; // Use one bit for stopbit.
config_1.Parity = NOPARITY; // No parity bit
config_1.BaudRate = CBR_9600; // Buadrate 9600 bit/sec
//---------------------------------------
if (statusPort_1 == FALSE) // if port is opened already, not open port
again.
{
handlePort_ = CreateFile(portName, // Specify port device: default "COM1"
GENERIC_READ | GENERIC_WRITE, // Specify mode that open
device.
0, // the devide isn't shared.
NULL, // the object gets a default
security.
OPEN_EXISTING, // Specify which action to
take on file.
0, // default.
NULL); // default.-
// Get current configuration of serial communication port.
if (GetCommState(handlePort_,&config_1) == 0)
{
AfxMessageBox("Problem occured in configuration.");
return FALSE;
}
config_1.ByteSize = 8; // Byte of the Data.
config_1.StopBits = ONESTOPBIT; // Use one bit for stopbit.
config_1.Parity = NOPARITY; // No parity bit
config_1.BaudRate = CBR_1200; // Buadrate 1200 bit/sec
// Set current configuration of serial communication port.
if (SetCommState(handlePort_,&config_1) == 0)
{
AfxMessageBox("Set configuration port has problem.");
return FALSE;
}
// instance an object of COMMTIMEOUTS.
COMMTIMEOUTS comTimeOut;
// Specify time-out between charactor for receiving.
comTimeOut.ReadIntervalTimeout = 3;
comTimeOut.ReadTotalTimeoutMultiplier = 3;
comTimeOut.ReadTotalTimeoutConstant = 2;
comTimeOut.WriteTotalTimeoutMultiplier = 0;
comTimeOut.WriteTotalTimeoutConstant = 0;
SetCommTimeouts(handlePort_,&comTimeOut);
// Updata port's status.
return TRUE;
}
else
{
AfxMessageBox("Port is Already Opened");
return TRUE;
}
}
// to write data to the port
void writePort(LPCVOID outputData,
const unsigned int& sizeBuffer,
unsigned long& length)
{
if (length > 0)
{
if (WriteFile(handlePort_, // handle to file to write to
outputData, // pointer to data to write to file
sizeBuffer, // number of bytes to write
&length,NULL) == 0) // pointer to number of bytes written
{
AfxMessageBox("writing of serial communication has problem.");
}
}
}
Tdk
|
|
|
|
|
How is your defined block of bits stored? Unless it is some character representation of a bit string, you can send the data as-is. For example, suppose you could do the following, using your code:
unsigned long defined_bits = 0x00000023;
unsigned long length;
writePort(&defined_bits,sizeof(defined_bits),length); This would write four bytes out the serial port: 0x23 , 0x00 , 0x00 , and 0x00 .
Let's suppose for a minute your 'defined bits' are in the form of a character string ('1', '1', '0', '0', '1', '1', '0' for example). Each byte you send is 8 bits. Convert your string of bits to bytes, 8 at a time, and send each byte.
char defined_bits[] = { '1', '1', '0', '0', '1', '1', '0' };
unsigned char data = 0x00;
unsigned char mask = 0x01;
for (int bit_index = 0; i < sizeof(defined_bits); bit_index++) {
if (defined_bits[bit_index] == '1') data |= mask;
mask <<= 1;
if (mask == 0x00) {
unsigned long length;
writePort(&data,sizeof(data),length);
data = 0x00;
mask = 0x01;
}
}
Software Zen: delete this;
|
|
|
|
|
Thanks Gary,
I implemented the hint you gave as follows.
<br />
char defined_bits[] = { '1', '0', '0', '0', '0', '0', '0', '0' };<br />
defined_bits[5] = '1';
<br />
unsigned char data = 0x00;<br />
unsigned char mask = 0x01;<br />
for (int bit_index = 0; bit_index < sizeof(defined_bits); bit_index++) <br />
{ <br />
if (defined_bits[bit_index] == '1') data |= mask; <br />
mask <<= 1; <br />
}<br />
CString w = CString(data);<br />
CString header = "ABCDE";<br />
<br />
CString tel6 = header +w ;<br />
<br />
unsigned long length;<br />
writePort(tel6,tel6.GetLength(),length);<br />
<br />
Also I changed the individual bits as ;
defined_bits[1] = '1';
Thanks a lot
TDK
ENTC
UoM
|
|
|
|
|
hi, i'm kind of new to the VC++ environment...
i have made my own class to add onto another program. my class creates a CFrameWnd and draws stuff on it. the problem is that i have scroll bars on the window, and i can not get my class to recognize the message maps (it acts like it never happened)...
this is my constructor and a small message box i made to try to catch the horizontal scroll bar message.
can any one help me figure out what i am doing wrong? thanks a bunch!
Bongo::Bongo(int X, int Y)
{
m_nScreenSizeX = X;
m_nScreenSizeY = Y;
RECT rectWindow;
rectWindow.top = 30;
rectWindow.bottom = rectWindow.top + m_nScreenSizeY;
rectWindow.left = 30;
rectWindow.right = rectWindow.left + m_nScreenSizeX;
BongoFrame = new CFrameWnd();
BongoFrame->Create(NULL, "Bongo App", WS_OVERLAPPED|WS_VSCROLL|WS_HSCROLL, rectWindow, NULL, NULL);
BongoFrame->ShowScrollBar(SB_BOTH,TRUE);
BongoFrame->ShowWindow(SW_SHOW);
BongoFrame->UpdateWindow();
BongoFrame->GetClientRect(rcClient);
pDC = BongoFrame->GetDC();
}
void Bongo::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
// TODO: Add your message handler code here and/or call default
AfxMessageBox("pop");
CFrameWnd::OnHScroll(nSBCode, nPos, pScrollBar);
}
|
|
|
|
|
when we declare a varible, where does it get stored at?
i know there is heap, stack, and etc.
Can you give me some details on how data structure variables get stored and accessed?
|
|
|
|
|
In a computer there is only one variable storage area, the main computer RAM. But, for the purpose of organization and performance, it is divided into several areas.
When you C/C++ program is started, memory is requested to the operating system to create the heap and the stack. Some may argue that your global variables need a third memory area, but this is not important for this discussion.
The heap is then managed by the C library if you are using C functions, like malloc or new. When you call malloc or new then a portion of the memory allocated at the start of the program is marked as used and returned to you, or, if this memory has exhausted, a new portion is requested to the operating system. If you are using Windows functions, like GlobalAlloc, then the principle is the same, in a sense that the memory you request will be marked as used and returned to you.
Both these memory areas use what we could call the heap (not the stack). They are accessed by dereferencing pointers, like in the code below:
struct S {
int x;
int y;
int z;
};
int main(void) {
S* var_s;
var_s=new S;
if (!var_s) return __LINE__;
var_s->y=20;
}
In this code, the structure S will have a total of 12 bytes (in Win32), because each integer takes 4 bytes. The new will return some relatively unpredictable address in memory, which is not that important. The only important value to check for is zero, which means the requested memory is not available (that's why the "if" statement is there).
The returned address is not important, but for this discussion let's pretend the value 1000 was returned. This value (1000) will thus be stored in var_s (below I'll tell you about where var_s resides). The line...
var_s->y=20;
... dereferences the pointer var_s, that is, uses it's value to access the memory. The var_s->y is thus translated to "memory address 1004", since address 1000 will contain the first of the 4 bytes of the "x" member, 1004 of the "y", and 1008 of the "z". So, after the translation to address 1004, the 4-byte value 20 will be stored there.
Note that even if you check what the value of var_s is, and find out it is 1000, that doesn't mean that your RAM memory chip that contains byte number 1000 is the one being used to store the data. That is because of virtual memory, which is responsible for allocating physical RAM chip addresses and assigning to logical addresses.
When your program starts, another area of memory is allocated, the stack. This memory is just like any other, but it is considered must more volatile, and besides it is also used to memorize where to go to when functions terminate. The stack is considered to be memory like "remember this for a moment while I do something else, and then I will get back to this". So, the organization is such that when you declare local variables (like var_s) a new 4 byte location is appended to the stack.
For example, when your program is started the stack could have been created at address 5000. The address to where the main function should return to is stored there, so a stack pointer will be used to store the value and advance. For example, suppose the 4 byte address value to where main should return when it finished is 7654. Then the stack pointer (which contains the value 5000) is used to place this address on the stack, and so the 4 bytes 5000, 50001, 50002, and 5003 will contain the 4 bytes of address 7654. The stack pointer is then advanced to position 5004.
When your program reaches the declaration of var_s the stack pointer is just advanced from 5004 to 5008, effectivelly allocating 4 bytes (from 5004 to 5007) for var_s. This is why var_s will contain garbage if you do not assign it a value in the declaration.
This variable, the var_s, and the main return address use normal RAM, like any other thing that should be memorized for fast access during execution, but are located in the organized structure we call stack. This fact has several consequences:
1) The address of the variable var_s is always known by using the stack pointer, which is a physical register of the processor.
2) The stack is very dense. Everything is packed together, and only the memory area after the stack pointer is free. Everything else from the start of the stack up to the stack pointer is densely occupied.
3) All the relative addresses of things stored in the stack are predictable. For example, while inside main, the return address could also be known, independently from where your program came from, by reading memory addresses 5000 to 5003 (4 bytes before the address of var_s). In reality, when main begins there is more stuff added to the stack which makes the var_s ocuppy addresses further from the main return address, but still it is possible to check all variables and function return addresses by navigating through the stack.
4) Although everything is accessible in the stack, by navigating in it, new things can be memorized only after previously memorized things. The stack can contain no holes, and that is the main diference to the heap. So, only the most recent things can be forgotten to release stack memory for new things. This means that you cannot forget the address of contents 5000 and use it for storing other things, unless you forget about var_s (at 5004) first.
(let me just point out that I am explaining the stack using the most natural logic but, in reality, the stack pointer is located first at the end of the stack area and is decremented as the stack becomes filled, i.e., the stack fills up backwards)
So, if I understood your question correctly, the answer is: things stored in the stack will occupy very predictable locations in the logical RAM address space. These things include the return address of functions, and local variables (which include parameters passed to functions, but if they are pointers then just the pointer values, not the memory to where they point to). Things allocated with malloc, new, or GlobalAlloc will occupy highly unpredictable locations in the logical RAM address space.
The logical address space has a highly unpredictable relation with physical address space (RAM chips) due to the translations performed by the virtual memory manager. This can even include transformations where the logical address space is larger than the physical space, and the portion that is missing in the RAM chips is allocated on your hard disk.
I hope this helps,
Rilhas
|
|
|
|
|
I wrote a class derived from CSliderCtrl to use the custom draw to paint the control in a dialog based app. I want to disable the focus rectangle from being drawn, but I cannot at all figure it out. Any help / ideas would be greatly appreciated.
|
|
|
|
|
overide the WM_SETFOCUS message. from that funtion, do not call the base calls function.
eg:-
void MySliderCtrl::OnSetFocus(CWnd* pOldWnd)
{
// CSliderCtrl::OnSetFocus(pOldWnd); this line is removed
}
nave
|
|
|
|
|
Hi, thanks for your response. I just tried that and it does not seem to work. When I use the keyboard to move the slider, the focus rectangle still appears.
|
|
|
|
|
It actually *should* work I believe, just that the control doesn't receive keyboard input since it doesn't have focus (if you think about it, if it never receives focus, it never has to draw the focus rect).
Since you can move the slider using the keyboard, it appears that your slider does actually have focus (unless you happen to be forwarding messages from the parent window).
Here's another method that works even though it has focus which I've used before. Just use custom draw and remove the CDIS_FOCUS bit from uItemState (uItemState &= ~CDIS_FOCUS) during the CDDS_PREPAINT phase.
The user might be confused without the focus rect though. I notice that windows media player 11 puts on the focus rect for a while if the slider actually has focus and receives keyboard input.
|
|
|
|
|
THANK YOU....removing that bit works like a charm. Its weird tho, because i figured the override OnSetFocus would've worked too, but it did not. And you were correct, I am forwarding WM_KEYDOWN messages from the parent window to the slider. I guess thats why. Thanks very much for your help.
|
|
|
|
|
I want to use CxImage (or others) to open multiple types of images (gif,jpg,bmp,ico etc) then transfer image files in memory (not save to disk) in bitmap format which includes BITMAPINFOHEADER and data.
any comments for how to use CxImage (or others) to do that?
|
|
|
|
|
I think you can use CImage by including atlimage.h if you are not using VC6.0
There is no dumb question
<bjay zhu@shanghai,="" china<="" b="">
|
|
|
|
|
Hey, i've used this lib in my app and it's really easy to use.
Read the docs that tell you which libs to include (depending on what image support you want) include them in your project, include the main header somewhere in your source.
bool CxImage::Load ( const TCHAR * filename, <br />
DWORD imagetype = 0 <br />
) [inherited]
Reads from disk the image in a specific format.
If decoding fails using the specified image format, the function will try the automatic file format recognition.
Parameters:
filename: file name
imagetype: file format, see ENUM_CXIMAGE_FORMATS
Returns:
true if everything is ok
bool CxImage::Encode ( BYTE *& buffer, <br />
long & size, <br />
DWORD imagetype <br />
) [inherited]
Saves to memory buffer the image in a specific format.
Parameters:
buffer: output memory buffer pointer. Must be NULL, the function allocates and fill the memory, the application must free the buffer, see also FreeMemory().
size: output memory buffer size.
imagetype: file format, see ENUM_CXIMAGE_FORMATS
use the Get...() functions to fill the header info
|
|
|
|
|