 |
 |
Apologies for the shouting but this is important.
When answering a question please:
- Read the question carefully
- Understand that English isn't everyone's first language so be lenient of bad spelling and grammar
- If a question is poorly phrased then either ask for clarification, ignore it, or mark it down. Insults are not welcome
- If the question is inappropriate then click the 'vote to remove message' button
Insults, slap-downs and sarcasm aren't welcome. Let's work to help developers, not make them feel stupid.
cheers,
Chris Maunder
The Code Project Co-founder
Microsoft C++ MVP
|
|
|
|
 |
For those new to message boards please try to follow a few simple rules when posting your question.- Choose the correct forum for your message. Posting a VB.NET question in the C++ forum will end in tears.
- Be specific! Don't ask "can someone send me the code to create an application that does 'X'. Pinpoint exactly what it is you need help with.
- Keep the subject line brief, but descriptive. eg "File Serialization problem"
- Keep the question as brief as possible. If you have to include code, include the smallest snippet of code you can.
- Be careful when including code that you haven't made a typo. Typing mistakes can become the focal point instead of the actual question you asked.
- Do not remove or empty a message if others have replied. Keep the thread intact and available for others to search and read. If your problem was answered then edit your message and add "[Solved]" to the subject line of the original post, and cast an approval vote to the one or several answers that really helped you.
- If you are posting source code with your question, place it inside <pre></pre> tags. We advise you also check the "Encode HTML tags when pasting" checkbox before pasting anything inside the PRE block, and make sure "Ignore HTML tags in this message" check box is unchecked.
- Be courteous and DON'T SHOUT. Everyone here helps because they enjoy helping others, not because it's their job.
- Please do not post links to your question in one forum from another, unrelated forum (such as the lounge). It will be deleted.
- Do not be abusive, offensive, inappropriate or harass anyone on the boards. Doing so will get you kicked off and banned. Play nice.
- If you have a school or university assignment, assume that your teacher or lecturer is also reading these forums.
- No advertising or soliciting.
- We reserve the right to move your posts to a more appropriate forum or to delete anything deemed inappropriate or illegal.
cheers,
Chris Maunder
The Code Project Co-founder
Microsoft C++ MVP
|
|
|
|
 |
Hi
I am looking to be Notified When something is downloaded to my FTP folder
towards that end I have implemented FindFirstChangeNotification being a mainframe programmer its taken a while to get used that when I do a Wait I stop the entire thread
So I have 2 options put the wait in a different thread or.... code a timer value other then infinite and in the case of WAIT_TIMEOUT loop "while(TRUE)" and Only "break when
the object is signaled
|
|
|
|
 |
Usually you don't stop an entire thread while waiting you are forced to do it with MFC, so I am guessing this is your MFC program again.
Within MFC personally I would create a thread which just spins it wheels checking whatever and the thread simply posts a message back when an interesting event occurs. I wouldn't be putting the wait I would be putting the whole code that requires the wait in a thread and use messages to communicate with the MFC code. So make a proper worker thread.
In vino veritas
|
|
|
|
 |
So you are saying creating a new thread to wait for notification is a better choice then an ifinate loop with say
A 1000 millisecond in the WaitForSingleObject only breaking out of the loop when the event is signaled
Truth is a new thread leaves the CPU time distribution up to Windows
Thanks
|
|
|
|
 |
It's a low priority Hotwatch .. it will always be better to do as a thread and it isn't hard
typedef struct _MYWATCHERDATA {
HWND AppWindow; UINT MsgId; WPARAM CmdId; char* FolderToWatch; HANDLE dwChangeHandles[2]; BOOL threadExitComplete; } WATCHERDATA;
DWORD WINAPI NotifyMeOfFolderChangeThread(LPVOID lpParam) {
BOOL exitSignal = FALSE; WATCHERDATA* watchData = (WATCHERDATA*)lpParam;
watchData->dwChangeHandles[0] =
FindFirstChangeNotification(watchData->FolderToWatch, FALSE, FILE_NOTIFY_CHANGE_FILE_NAME);
if (INVALID_HANDLE_VALUE == watchData->dwChangeHandles[0]) {
DWORD dwError = ::GetLastError();
return dwError;
}
while (exitSignal == FALSE) {
DWORD dwWaitStatus = WaitForMultipleObjects(2,
watchData->dwChangeHandles, FALSE, INFINITE);
switch (dwWaitStatus) {
case WAIT_OBJECT_0:
PostMessage(watchData->AppWindow, watchData->MsgId,
watchData->CmdId, (LPARAM)watchData->FolderToWatch);
FindNextChangeNotification(watchData->dwChangeHandles[0]);
break;
case WAIT_OBJECT_0 + 1:
exitSignal = TRUE; break;
}
}
watchData->threadExitComplete = TRUE; return 0;
}
The use of the thread involves, initialize, use, wait for thread to exit .. cleanup
char* watchDirectory = "c:\\temp\\"; // Some directory to watch
WATCHERDATA* myWatch = (WATCHERDATA*) malloc(sizeof(WATCHERDATA)); // Allocate memory
myWatch->AppWindow = myAppHandle; // Application window handle
myWatch->MsgId = WM_APP + 100; // Some private application message ID
myWatch->CmdId = 1; // Some private id we might have multiple watches
int len = strlen(watchDirectory) + 1; // size of string
myWatch->FolderToWatch = (char*) malloc(len); // Allocate string space
strcpy_s(myWatch->FolderToWatch, len, watchDirectory); // Copy string to allocated memory
myWatch->dwChangeHandles[0] = 0; // Clear thread handle one .. thread itself uses that
myWatch->dwChangeHandles[1] = CreateEvent(0, FALSE, FALSE, "EXIT");// Set thread handle two for us to force exit
myWatch->threadExitComplete = FALSE; // Thread will set this on complete
// Use thread
HANDLE workerThread = CreateThread(NULL, 0, NotifyMeOfFolderChangeThread, myWatch, 0, NULL);
// Change thread priority
SetThreadPriority(workerThread, THREAD_PRIORITY_LOWEST);
// This will do a simple 10 sec wait .. simulating doing something
Sleep(10000);
// Ok manually terminate the thread
SetEvent(myWatch->dwChangeHandles[1]);
// Wait for thread to signal it has finished with myWatch
while (myWatch->threadExitComplete == FALSE) {};
// Okay you are free to cleanup myWatch
free(myWatch->FolderToWatch);
free(myWatch);
In vino veritas
|
|
|
|
|
 |
Leon
Just wanted to tell you again you are correct I have Sockets in my code
So Typically after I do CAsynSocket connect I do the send after I get the OnSend Notification
From The FrameWork
My Sockets has a CWinThread Wrapper, However the notification like OnSend comes in
The Context of the Main Thread
Since I put WaitFor...Object api (In The Main Thread) even though I didn't have INFINITE
it messed up the Windows Dispatcher and I wasn't getting the notification
I am going to try your code out Shortly
Thanks again
|
|
|
|
 |
Yes that is a generic schema for not doing that sort of thing ... I hacked the MSDN thread sample.
When I do socket apps I do exactly the same schema I have a write thread and a read thread of exactly
the form above. The socket IO structures and objects are held in the memory block.
Basically you want your app just dealing with messages not sitting around doing things .. bring up task
manager and look at the number of threads running normally. It really expects and wants this sort of
behaviour, it's designed around it.
Lifetime of app threads in particular are extremely easy because you can launch them on the WM_CREATE
of the main app window and dispose of them in the WM_DESTROY. You don't have the problem of who is
responsible for the shared data and memory (and it's cleanup) that you have with intermittent start
and stop threads. The app window handle to pass to the thread to message you also can't get wrong
They give you huge blocks of message ids at WM_APP and WM_USER to allow you to do it. All those ID's
you are free to use but you might want to check MFC might use a few (that is why I jumped 100) and
they may restrict the range down a little.
In vino veritas
|
|
|
|
 |
I have a device (Fluke data logger which uses 9600-8-N-1 and no flow control) for which I need to write an serial interface in Visual Studio 2010 (C++) but have not been able to get more than a single response from the unit. I can connect, send the request for (as an example) device identification, but subsequent requests for data from the unit produce no response (variable read remains equal to zero after each Readfile request). I know the unit works fine because I can use a standard terminal program to obtain the responses I a need.
Nothing in the forums here, on MSDN, or repeated Google searches seems to answer my question. This has been frustrating me for more than a week so I am looking for a fresh set of eyes to point out what I am probably missing.
This is a stripped-down version of the test code. Any ideas are welcome. For purposes of testing the device response I'm not using overlapping for testing, but will employ overlapping in the "real" code.
#include "stdafx.h"
#include <stdio.h>
#include <conio.h>
#include <string.h>
#define STRICT
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
int _tmain(int argc, _TCHAR* argv[])
{
int ch;
HANDLE screen = GetStdHandle(STD_OUTPUT_HANDLE);
printf("Getting keyboard mode\n");
HANDLE keyboard = GetStdHandle(STD_INPUT_HANDLE);
DWORD mode;
if (!GetConsoleMode(keyboard, &mode))
{
printf ("GetConsoleMode failed with error %d.\n",
GetLastError());
}
printf("Setting keyboard mode\n");
mode &= ~ ENABLE_PROCESSED_INPUT;
if (!SetConsoleMode(keyboard, mode))
{
printf ("SetConsoleMode failed with error %d.\n",
GetLastError());
}
printf("opening comm port\n");
TCHAR *port_name = TEXT("COM1"); HANDLE file;
file = CreateFile(port_name,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL);
if ( INVALID_HANDLE_VALUE == file) {
printf ("CreateFile failed with error %d.\n",
GetLastError());
CloseHandle(file);
if ( _kbhit() ) {
ch = _getch();
}
return 1;
}
printf("Getting com state\n");
DCB port;
SecureZeroMemory(&port, sizeof(port));
port.DCBlength = sizeof(port);
if (!GetCommState(file, &port))
{
printf ("GetCommState failed with error %d.\n",
GetLastError());
CloseHandle(file);
if ( _kbhit() ) {
ch = _getch();
}
return 1;
}
printf("Building com state\n");
TCHAR *DCBsettings = TEXT("baud=9600 parity=n data=8 stop=1");
if (!BuildCommDCB(DCBsettings, &port))
{
printf ("BuildCommDCB failed with error %d.\n",
GetLastError());
CloseHandle(file);
if ( _kbhit() ) {
ch = _getch();
}
return 1;
}
printf("Adjusting com settings\n");
if (!SetCommState(file, &port))
{
printf ("SetCommState failed with error %d.\n",
GetLastError());
CloseHandle(file);
if ( _kbhit() ) {
ch = _getch();
}
return 1;
}
printf("Setting port time-outs.\n");
COMMTIMEOUTS timeouts;
timeouts.ReadIntervalTimeout = 1;
timeouts.ReadTotalTimeoutMultiplier = 1;
timeouts.ReadTotalTimeoutConstant = 1;
timeouts.WriteTotalTimeoutMultiplier = 1;
timeouts.WriteTotalTimeoutConstant = 1;
if (!SetCommTimeouts(file, &timeouts))
{
printf ("SetCommTimeouts failed with error %d.\n",
GetLastError());
CloseHandle(file);
if ( _kbhit() ) {
ch = _getch();
}
return 1;
}
printf("Writing *idn?<cr> to port\n");
char init[] = "*idn?\n";
DWORD written;
if (!WriteFile(file, init, sizeof(init), &written, NULL))
{
printf ("WriteFile failed with error %d.\n",
GetLastError());
}
if (written != sizeof(init))
{
printf("not all data written to port\n");
}
char buffer[256];
memset(&buffer[0], 0, sizeof(buffer));
DWORD read;
char dataReq[] = "fetch? 3\n";
int i;
do {
if( !ReadFile(file, buffer, sizeof(buffer), &read, NULL) )
{
printf ("ReadFile failed with error %d.\n",
GetLastError());
}
if (read){
printf ("Characters read = %d.\n",
read);
for(i=0; i<(read+1); i++)
{
printf("%d ", buffer[i]);
}
printf("\n");
printf("%s\n", buffer);
memset(&buffer[0], 0, sizeof(buffer));
Sleep(1000);
printf("Writing fetch? 3<cr> to port\n");
if (!WriteFile(file, dataReq, sizeof(dataReq), &written, NULL))
{
printf ("WriteFile failed with error %d.\n",
GetLastError());
}
if (written != sizeof(dataReq))
{
printf("not all data written to port\n");
}
}
if ( _kbhit() ) {
ch = _getch();
WriteFile(file, &ch, 1, &written, NULL);
}
} while ( ch != 127);
CloseHandle(keyboard);
CloseHandle(file);
return 0;
}
|
|
|
|
 |
Have you tried, lengthening your timeouts, or even disabling them (but then you need to read 256 bytes in order to return) ?
"the debugger doesn't tell me anything because this code compiles just fine" - random QA comment
"Facebook is where you tell lies to your friends. Twitter is where you tell the truth to strangers." - chriselst
"I don't drink any more... then again, I don't drink any less." - Mike Mullikins uncle
|
|
|
|
 |
I tried both lengthening the timeouts and rewriting the code using overlapped communication as per bt[^] but the result is the same. First command is received and I can get a response. The second command, while sent without error, is followed by no response.
If it helps, after running the code I have to run the terminal program and issue a command twice to get it back to a responsive state. Otherwise running the code twice in a row doesn't even return anything for the first command. It's like it gets stuck waiting after sending the response.
|
|
|
|
 |
Could the terminal program be appending and sending a necessary line feed or carraige return, that the other device needs?
"the debugger doesn't tell me anything because this code compiles just fine" - random QA comment
"Facebook is where you tell lies to your friends. Twitter is where you tell the truth to strangers." - chriselst
"I don't drink any more... then again, I don't drink any less." - Mike Mullikins uncle
|
|
|
|
 |
I already append a carriage return (the documentation says either a carriage return or linefeed will be accepted). Even adding extra CRs and LFs has no effect.
|
|
|
|
 |
Could you connect a PC with a terminal program in place of the device and see what is being sent by your app and make sure it is OK?
"the debugger doesn't tell me anything because this code compiles just fine" - random QA comment
"Facebook is where you tell lies to your friends. Twitter is where you tell the truth to strangers." - chriselst
"I don't drink any more... then again, I don't drink any less." - Mike Mullikins uncle
|
|
|
|
 |
I tried different timeouts and the following work for the first read:
CTimeouts.ReadIntervalTimeout = 20; CTimeouts.ReadTotalTimeoutMultiplier = 10; CTimeouts.ReadTotalTimeoutConstant = 100; CTimeouts.WriteTotalTimeoutMultiplier = 0; CTimeouts.WriteTotalTimeoutConstant = 0;
I also added a loop using ClearCommError to verify that cbInQue has returned before performing ReadFile so was able to do that as soon as data arrived. Everything in that first request-receipt cycle works fine.
I still have the problem that the next WriteFile is essentially ignored, although it is sent without errors. The device appears to be waiting for something after the read was completed before it can respond to whatever is sent on the transmit line.
|
|
|
|
 |
Does WriteFile say bytes sent > 0? Do you see data on the wire (a breakout box might be handy)?
Can you connect a PC with a terminal program in place of the device (with a null modem cable) so you can see (and verify) what, if anything is being sent by your program and manually send the data you expect to get. A scenario where you could set break points and see exactly what code is being executed and the value of the variables.
"the debugger doesn't tell me anything because this code compiles just fine" - random QA comment
"Facebook is where you tell lies to your friends. Twitter is where you tell the truth to strangers." - chriselst
"I don't drink any more... then again, I don't drink any less." - Mike Mullikins uncle
|
|
|
|
 |
It ended up that I had to force-transmit a carriage return after the ReadFile to "kick" the device using TransmitCommChar. After the "kick" it responds to the next WriteFile with the appropriate response. Using a second PC was going to be my next course of action.
|
|
|
|
 |
First housekeeping when you open a comport you really need to put the colon in ... its "COM1:".
Yes your string works on some versions of Windows but not all, the documentation spells it out
To open a serial port
- Insert a colon after the communication port pointed to with the first parameter, lpzPortName.
For example, specify COM1: as the communication port.
In the ReadFile documentation it spells out the blocking function.
ReadFile function (Windows)[^]
You will have an error which will be a Readtimeout. Why because you set the read timeout to
1 second and execute a read and there won't be any data because you haven't yet sent another
command.
From that moment on you are toast as your code does not ever clear the error condition and
ReadFile will always return with reading zero bytes because you haven't cleared the error.
The big obvious is there isn't even a single GetLastError in your code much less dealing
with the error. The reason the terminal program fixes the problem is at some point they go
and clear the error.
You could try brutal and SetLastError to zero just before the ReadFile .. I don't like it
but it will probably work
While the thread error variable has an error value I am pretty sure that none of the IO
functions will work so I am pretty sure WriteFile will also bail always writing zero
bytes while it's set. It should also return success but the actual bytes written will
always be zero because the fail out is for pre-existing error that hasn't been cleared.
I don't particually like the way you are using the com port but probably the easiest way
to fix you problem is make the ReadFile timeout bail immediately .. so set no timeout on
the read. How to do that is given in the documentation
COMMTIMEOUTS structure (Windows)[^]
Quote => "A value of MAXDWORD, combined with zero values for both the ReadTotalTimeoutConstant
and ReadTotalTimeoutMultiplier members, specifies that the read operation is to return
immediately with the bytes that have already been received, even if no bytes have been
received."
That should stop you getting a read timeout which should fix your problem with your current code
and it getting into a block condition. It just means it will spin around your do loop like a crazy
person rather than slow 1 second pace it currently is.
On the plus side it will be more responsive
However you really need to actually put in code to deal with errors, you set the com timeouts
but do nothing if the timeout or any other error actually occurs.
In vino veritas
modified 2 days ago.
|
|
|
|
 |
Excellent points and suggestions, and I've implemented much of what you suggested. In the end it turned out the device was waiting for a response from the computer to indicate the read was completed, which I accomplished with a TransmitCommChar. Clunky but it works.
|
|
|
|
 |
Much thanks to all who made suggestions. I implemented many of them.
In the end, the problem was solved by "kicking" the device with TransmitCommChar(hComm, 13); after the read request.
|
|
|
|
 |
If anyone has a minute can they confirm a weird behaviour of _tcscpy_s which caught me totally off guard that it trashes the unused part of the return buffer.
The code I would like you to test follows, you will need include TCHAR.H for the standard _tcscpy_s function
#include <TCHAR.H>
TCHAR szFilter[512];
memset(szFilter, 0, sizeof(szFilter)); _tcscpy_s(szFilter, _countof(szFilter), _T("All files"));
int i = _tcslen(szFilter);
TCHAR Ch1 = szFilter[i + 2];
memset(szFilter, 0, sizeof(szFilter)); _tcscpy_s(szFilter, _tcslen(_T("All files"))+1, _T("All files"));
TCHAR Ch2 = szFilter[i + 2];
What I am interested in is the part of the buffer the result is not written in. What stunned me was it was all trashed.
Okay the function does not define what it does with the unused parts of the buffer but it seems a waste of time to play with it.
The stranger part is if you lie to the function and make it have just the right size buffer it doesn't trash the buffer.
It's so quirky I am trying to work out if it is a machine/processor dependent implementation of the function.
In vino veritas
|
|
|
|
 |
I have seen this before and I think it is to do with the fact that the _s variants are "safe" mode functions. The first thing they do is to overwrite the buffer with some known pattern (hex FEFE in my Unicode test), before doing the copy - at least in Debug mode. You could try a Release mode version and add some code to examine the buffer at each point. A 16 character buffer will be big enough.
|
|
|
|
 |
Yes it's hex FEFE pattern for me as well. I tried release and it's not there .. must be something to do with debug mode.
That is what was doing my head in a code that would run in release mode but not in debug mode ... now that is a turn up.
Update: David Crowe got the weirdness there is a FILL_STRING call put on the balance of the buffer. I can't for the life of me think why they do it so have referred it to Microsoft as to why debug mode does it, and will work around the behaviour.
In vino veritas
|
|
|
|
 |
Just confirmed this using ordinary strcpy_s, so nothing to do with TCHARs. Also when I run it in Release mode the buffer is not filled with the xFE characters.
|
|
|
|
|
 |
A good catch that does the job. Setting it to zero and then putting the value back after the code solves my problem.
Well you learn something everyday, I was completely unaware they had added that functionality into the safe routines but at least they do realize the problem and allow control of it.
In vino veritas
|
|
|
|
 |
I reckon it has something to do with _tcscpy_s() internally calling _FILL_STRING() for the balance of the destination string. If you can live without the safe version, _tcscpy() will work as expected.
It looks like you may need to use memcpy() instead.
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"You can easily judge the character of a man by how he treats those who can do nothing for him." - James D. Miles
modified yesterday.
|
|
|
|
 |
You are correct the FILL_STRING is the culprit and no I need the function so will just do the buffer fill long handed. As Richard worked out it isn't there in release mode so it's something to do with debug mode display functions. My guess is it's a pattern for there watch for change implementation.
It did however totally catch me out
Update: Chris correctly identified why it's doing it and how you control it.
In vino veritas
modified yesterday.
|
|
|
|
 |
leon de boer wrote: ...so will just do the buffer fill long handed. Just curious but what does it matter what's after the \0 value in the buffer?
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"You can easily judge the character of a man by how he treats those who can do nothing for him." - James D. Miles
|
|
|
|
 |
I was try to make a filter for OPENFILENAME
OPENFILENAME structure (Windows)[^]
It's not a great structure from MS and it look something like this "DXF Files\0*.dxf\0PLT Files\0*.plt\0\0 "
You can't string copy that in because of the terminating 0 characters in it.
For me it's worse "DXF files", "PLT files" is the English version I have German, French etc strings
to replace it so the string changes.
So I have to build that structure and the old code basically relied on the buffer being zeroed
and it just wrote the string bits in without having to track all the string lengths. It was assumed
strcpy doesn't play with parts of the buffer it isn't writing the result into.
So the correct way to write it would be strcpy + strcat + strcat + strcat + strcat(\0).... which I did.
The safe functions mean you have to track the amount of buffer left to pass in and so it becomes
a lot of code for a very trivial thing ... BUT IT'S GUARANTEED TO WORK
So basically while I was trying to debug the program the code was failing because the code relied
on something not guaranteed. For such a simple string structure its a pain to have to make code
track multiple string pointers just to create it but I should have done it .. lesson 1 never assume
anything not actually specified!!!!
The bigger issue for me and why I went after it was performance. If they are playing around with
stuff they don't need to they are wasting time. String functions are used often and everywhere
and on very large memory blocks and I was concerned about the impact.
In vino veritas
modified yesterday.
|
|
|
|
 |
leon de boer wrote:
You can't string copy that in because of the terminating 0 characters in it. Why would you want to? The lpstrFilter member is a pointer not an "array". You should have something like:
OPENFILENAME ofn = {0};
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.lpstrFilter = "DXF Files\0*.dxf\0PLT Files\0*.plt\0"; ...Now if you are wanting a dynamic filter (one that changes at runtime), that's a horse of a different color, although still do-able.
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"You can easily judge the character of a man by how he treats those who can do nothing for him." - James D. Miles
|
|
|
|
 |
Edit: Correction yes that works as a static.
But yes that is a static create but my strings are coming from memory the user can switch language on the fly and the number of types of file that can be loaded depends on version purchased. Bascially I can't possible do it with static strings I have to build the string into an array and pass the pointer to the array. The array is created and disposed of by the dialog and all very normal when doing multilingual dialog functions.
Many of the string bits are coming from windows via the locale API and heaven only knows how long they are and where they are coming from in memory.
I need the array because I have to assemble all the string somewhere.
I would like to see a dynamic form of your code without allocating an array on the heap or local stack
Anyhow it's all working now, the performance was more the issue to me and that is resolved.
In vino veritas
modified yesterday.
|
|
|
|
 |
leon de boer wrote:
I need the array because I have to assemble all the string somewhere. Like was previously mentioned, you may need to use memcpy().
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"You can easily judge the character of a man by how he treats those who can do nothing for him." - James D. Miles
|
|
|
|
 |
Hi, I am new in MFC vc++ Please help me to come out from an major issue.
I want to move an object(Image,Rectangle) ..etc in Canvas buy using Arrow Key(left,right,up,down) in MFC VC++ application.only i get OnKeyDown()function I am not able to use this OnKeyDown()function to get keyboard event. please provide a proper code
|
|
|
|
|
 |
Hi Chris Losinger Yes this is dialog-based application but arrow key functionality i need to apply in canvas/editor not in dialog.
Thanks
|
|
|
|
 |
I am learning how to use ellipsis in function. Started with putting "int" as parameters, with first entry being count of parameters passed to he function. Now I want to pass multiple types , not just int , to the function. The following snippet will do, but...
How do you get "type" from passing a char * - in this case "format" variable? What did I missed ?
Thanks for your help. Vaclav
I am not sure if I tagged the code properly.
<pre lang="c++"> void my_printf( char *format, ... ) { va_list argptr;
va_start( argptr, format );
while( *format != '\0' ) { // string if( *format == 's' ) { char* s = va_arg( argptr, char * ); printf( "Printing a string: %s\n", s ); } // character else if( *format == 'c' ) { char c = (char) va_arg( argptr, int ); printf( "Printing a character: %c\n", c ); break; } // integer else if( *format == 'd' ) { int d = va_arg( argptr, int ); printf( "Printing an integer: %d\n", d ); }
*format++; }
va_end( argptr ); } </pre>
|
|
|
|
 |
That code looks like it should broadly work, but you are assuming any 's', 'c', or 'd' in the string is a format identifier. Your main loop should iterate the characters of the format string, copying them to the output until you see a format specifier. When you see a '%' character then you know that is the start of a formatting sequence so you need to get the width, precision and type details. Once you have extracted all those values, then you can process the next argument according to the type field character.
|
|
|
|
 |
My feeling exactly. I this whoever posted the code missed something.
Here is their sample use of the function.
int main( void ) {
my_printf( "sdc", "This is a string", 29, 'X' );
return( 0 ); }
This code displays the following output when run:
Printing a string: This is a string Printing an integer: 29 Printing a character: X
Now where is the "sdc" print?
And I thought that "format" was some kind of special feature. I guess I ditch this, maybe I can figure out how to use templates.
Thanks
|
|
|
|
|
 |
As per what Richard said READ THE MANUAL.
"sdc" is the format specifier for the three parameters that follow
s = STRING
d = Signed decimal integer
c = Character
"This is a string" they want displayed as a string
29 they want displayed as a decimal
X they want displayed as a character
Try changing changing "sdc" to "s%.3fc" and watch the output
%.3f is a complex format it means write value as a float to 3 decimal places.
So we still have 3 instructions s + %.3f + c
So the first string is a FORMAT STRING it tells the print function what to do with the following data passed in.
In vino veritas
|
|
|
|
 |
i use ncrack and in installed all this(visual studio 2005,2008,2010,2013) so ncrack working with visual c++. im wondering how can i create more threads?i foudn this but i don't know how to apply!I must open visual c++?create project?
<a href=""><a href="http://msdn.microsoft.com/en-us/library/ms682516(VS.85).aspx">Creating Threads (Windows)</a>[<a href="http://msdn.microsoft.com/en-us/library/ms682516(VS.85).aspx" target="_blank" title="New Window">^</a>]</a>
|
|
|
|
 |
Member 11189357 wrote: must open visual c++?create project? Yes, because threads can only exist within an executable program. However, your question or problem is far from clear.
|
|
|
|
 |
Try this:
#include "stdafx.h"
#define _MT
#include <windows.h>
#include <process.h> /* _beginthread, _endthread */
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "libcmt.lib")
#pragma comment(linker, "/NODEFAULTLIB:libcd.lib")
void ThreadFunction1(void *ch);
void ThreadFunction2(void *dummy);
BOOL repeat = TRUE;
int main(){
printf("\nMultithreading with two threads.\n\n");
printf("Thread Function 2 listens for key strokes. \n");
printf("Thread Function 1 does all the other work \n");
printf(" \n");
CHAR ch = 'A';
_beginthread(ThreadFunction2, 0, NULL);
while (repeat){
_beginthread(ThreadFunction1, 0, (void *)(ch++));
Sleep(1000L);
}
printf(" \n");
return 0;
}
void ThreadFunction2(void *dummy){
_getch();
repeat = 0;
}
void ThreadFunction1(void *ch){
while (repeat){
Sleep(100L);
}
_endthread();
}
|
|
|
|
 |
For windows right?so this source will work for ncrack force bruter right?I don't know how to sue this code?must open visual c++ ?
-- modified 5 days ago.
|
|
|
|
|
 |
yes i use 20-30 threads if i use more i receive errors,nsock timeouts! nsock errors! etc...so i need to put that code somewhere but i don't know how?
|
|
|
|
 |
Member 11189357 wrote: i need to put that code somewhere but i don't know how? And you think maybe we can guess? We have no idea what your code is supposed to be doing, or what you are trying to achieve with these threads.
|
|
|
|
 |
ncrack -vv -d7 --user admin -P list1.txt 81.196.251.12:3389,CL=20,cd=320ms -oN good.txt -f
CL=means maximum threads 20 , becouse if i use more...i receive nsock errors tools i use are ( ncrack +visual c++)
-- modified 5 days ago.
|
|
|
|