|
There is an edit link below your post which should be used rather than posting a new question.
There is also a delete link. Please use that to delete your first question.
To write the elements to a text file, you may open the file using fopen() and then print the elements using fprintf() :
FILE *f = fopen(fileName, "wb");
fprintf(f, "%lf %lf %lf\r\n", newForce.x, newForce.y, newForce.z);
fprintf(f, "%lf %lf %lf\r\n", newForce1.x, newForce1.y, newForce1.z);
fclose(f);
Depending on the required accuray it may be necessary to specify the number of significant digits to be printed (see the printf() format specifications).
[EDIT]
The above is for Windows text files. For Unix text files remove the '\r' from the fprintf() format strings.
|
|
|
|
|
Hey Thank you Jochen!.
Im just wondering how can i make use of a buffer where intitially I can dumb my data..and once the execution is completed writing into a file..do you have a suggestion?.
|
|
|
|
|
You can do it similar using sprintf() to print to a buffer and then write the buffer to file:
char buffer[128];
char *p = buffer;
int n = sprintf(p, "%lf %lf %lf\r\n", newForce.x, newForce.y, newForce.z);
s += n;
sprintf(p, "%lf %lf %lf\r\n", newForce1.x, newForce1.y, newForce1.z);
FILE *f = fopen(fileName, "wb");
fwrite(buffer, 1, strlen(buffer), f);
fclose(f);
But as you can see this is much more code and it is insecure without checking for buffer overflows (which adds more code).
If you don't need the data to be in text format (e.g. only loaded by your application), it might be better to write the data to a binary file. That solves also the problem of inaccuracies when converting floating point values to text and back again later.
Example:
FILE *f = fopen(fileName, "wb");
fwrite(&newForce.x, sizeof(newForce.x), 1, f);
fclose(f);
Reading is then done in a similar way:
FILE *f = fopen(fileName, "rb");
fread(&newForce.x, sizeof(newForce.x), 1, f);
fclose(f);
|
|
|
|
|
Many thanks Jochen!! .
I'm planning to use just one file containing information about two forces, something like this:
timestamp newforce(X Y Z) newForce1(X Y Z))
where the values of x,y,z will be in column.
fprintf(pFile, "%lf %lf %lf\r\n %lf %lf %lf\r\n", newForce.x, newForce.y, newForce.z, newForce1.x, newForce1.y, newForce1.z);
do you think it's a right assignment?, I mean how can I write data effectively into the file with proper indentation?
|
|
|
|
|
You can use the printf format specifiers (see http://www.cplusplus.com/reference/cstdio/printf/[^]).
Using the width specifier, all numbers will have the same width padded with blanks. For proper alignment of the decimal point you should also use the precision specifier and the flag specifier (use a space or minus). The final values to be used depend on the range of your values and the required precision. Assuming a range up to (but excluding) 100 and a precision of 2 fractional digits:
Precision = 2
Width = 1 (sign) + 2 (digits) + 1 (decimal point) + 2 (digits) = 6
Then use the format "% 6.2f" for each value:
fprintf(pFile, "% 6.2f % 6.2f % 6.2f\r\n% 6.2f % 6.2f % 6.2f\r\n",
newForce.x, newForce.y, newForce.z, newForce1.x, newForce1.y, newForce1.z);
For the time stamp you can use the strftime()[^] function.
modified 18-Mar-15 13:08pm.
|
|
|
|
|
I tried as u suggested , but now the data I'm getting is kind of overflowing, I mean it's always generating a data txt file of 1kb!!
|
|
|
|
|
You may give an example of your data. Inspecting the text file may also give a hint what is going wrong.
[EDIT]
I have replaced the usage of "%lf" by "%f" in my post. But this should make no difference with MS compilers.
modified 18-Mar-15 13:09pm.
|
|
|
|
|
Hi Jochen,
I'm getting data like this
18832315686612578000000000000000000000000000000000000000000000000000.00 18832315686612578000000000000000000000000000000000000000000000000000.00 18832315686612578000000000000000000000000000000000000000000000000000.00
18832315686612578000000000000000000000000000000000000000000000000000.00 18832315686612578000000000000000000000000000000000000000000000000000.00 18832315686612578000000000000000000000000000000000000000000000000000.00
It's 2 raws of numbers..3,5 lines are continuation of 1st line..ans so 4,6 ..
It's basically limited to 1kb irrespective of the duration of experiment
|
|
|
|
|
That are quite large numbers. Are they the correct values? If your numbers are in that range, you should use the "%E" format.
|
|
|
|
|
Hi Jochen,
Now it's working perfectly!. I did a a mistake in closing the file. Thank you so much for your prompt and precise feedback!.
|
|
|
|
|
Fine that all is working now and thank you for the feedback.
|
|
|
|
|
Hi Jochen,
The data i'm getting is of very large sample. I use a inbuilt thread class calls at very high frequency. Basically I want to reduce the sampling rate so that I'll get significant data with less samples..Do you have any idea how to create periodic thread with a fixed frequency?
|
|
|
|
|
It is difficult to answer this without knowing how samples are triggered, new data are signaled, and what is done by your thread class.
When sampling is triggered by your app, you can control the frequency. If it is free running you may skip samples (e.g. processing only every second one).
When using a worker thread you usually call a wait function (e.g. WaitForSingleObject ) that returns upon events or a time out. The time out value can be used for periodic execution.
|
|
|
|
|
Basically two functions one is for updating graphics and other for haptics rendering. Haptic rendering sampling rate is quite large compared to graphics. In the library I'm using there is a thread class basically gives priority to haptic and graphics rendering. But I'm not able to see any section in the code where they access system timing and setting sampling rate etc.
I'm thinking about assigning some condition inside data will be written into the file at a rate of 100 samples per second. There is an inbuilt precision clock with the library, so if I've I can get cpu time with precision clock , how can formulate a condition to write data at a rate 100Hz??
|
|
|
|
|
As far as I understood you have a haptic device which is some kind of hardware which generates data at a frequency defined by the hardware. If the library does not provide functions to set the sample rate, it is probably fixed. The thread is then activated when new data are available.
But again, without knowing the hardware and the library (which acesses the hardware specific driver), it is rather impossible to answer.
Do you want to write the data to a file with 100 Hz. This is probably too fast (especially when the file must be opened for each write). It again depends on your requirements (who is reading the file). If the data should be read by another process, you may use some kind of IPC (Inter Process Communication).
Regarding timers:
Windows has no high resolution timers. While it is possible to measure times with high resolution (QueryPerformanceCounter), the system timers have a resolution of about 10 ms by default and can be tweaked down to 1 ms.
|
|
|
|
|
Jochen Arndt wrote: the system timers have a resolution of about 10 ms by default and can be tweaked down to 1 ms.
What about the waitable timers? SetWaitableTimer[^]
Quote: pDueTime [in]
The time after which the state of the timer is to be set to signaled, in 100 nanosecond intervals.
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
Windows uses internally 100 ns based times (FILETIME structure). But this does not mean that the internal timer tick is running with a resolution of 100 ns.
There are undocumented functions to query the range of resolution and set the resolution (NtQueryTimerResolution , NtSetTimerResolution ). On a typical system, the range is 0.5 to 15.6 ms.
|
|
|
|
|
How can I configure a periodic thread of particular frequency?
|
|
|
|
|
Just call Sleep() with a time out value of 1000 / frequency[Hz].
A better implememntation would use WaitForSingleObject() with the same time out value and a handle to a terminate thread event so that you can terminate the thread:
UINT worker_thread_func(LPVOID pParam)
{
MyClass *pThis = (MyClass *)pParam;
HANDLE hKillEvent = pThis->m_hKillEvent;
while (1)
{
if (WAIT_OBJECT_0 == WaitForSingleObject(hKillEvent, TIME_OUT_VAL))
break;
}
return 0;
}
|
|
|
|
|
Hi Jochen,
I still didn't get idea of using WaitForSingleObject() as a timer. Basically WaitForSingleObject is a predefined function under windows.h? right?. Can you bit explain how exactly this can be embedded with a project?
|
|
|
|
|
It is a Windows API function that is used with threads. It will suspend the thread until the event specified by the passed handle occurs or the time out time has elapsed.
Using threads is an advanced topic. So you should read about it first. A starting point may be Using Worker Threads[^].
Your requirement was to execute specific tasks in fixed intervals. This can be done by Windows timers from within your main (GUI) thread. But this will block the main thread for the task execution time. With short intervals, this will lead to delayed user input (mouse and keyboard actions are not performed immediately). To avoid this, a worker thread can be used.
|
|
|
|
|
Message Closed
modified 30-Mar-15 8:31am.
|
|
|
|
|
I can't answer this without knowing the library.
That depends on the library, the implementation of that 'clock' and if it can generate some kind of signal.
|
|
|
|
|
Hi Everyone..
I very rarely ask programming-specific questions in public forums, but this one has me completely stumped.
I just can't seem to get the Windows Native API function, "Shell_NotifyIcon" to work, no matter what I try.
This is the Windows API function that enables an application to add its "Icon" to the Windows System Tray, aka: the "System Notification Area", and then enables it to pop up "notifications", etc..
At least, in theory..
No matter what I try however, this function always fails in my app.
And when I call the GetLastError() function to try to determine what was allegedly wrong with the call, sometimes I'll get a "timeout" error (whatever that means), sometimes I'll get an "invalid window handle" (but the handle's perfectly valid), and other times the call will actually succeed, but the very next call will fail with the same variable results..
I'm compiling in Windows 64-bit using Visual C++ Express, BTW..
I've tried calling both the ANSI and Unicode versions of this function and get the same results. I've tried specifying different "versions" to this function (it's a parameter), and I get the same results. I've tried compiling both with and without "enabling Visual Styles", but, you guessed it, same results..
And I've looked at all the sample code on the Internet that uses this function, including most of the code on this site, and without exception, none of the code I've looked at is doing anything more than my own code is doing..
Which is all, needless to say, exceedingly frustrating..
My app also changes its own execution priority, so I took that out to see if it would make a difference - it didn't..
I also came across an excellent article on Shell_NotifyIcon on the Internet:
"The trouble with Shell_NotifyIcon()"]
So I implemented a retry count, as he suggested. Unfortunately, the only difference that made was that I had to wait four seconds before I could see it fail (yet again)..
The methodology involved is this:
my Main Dialog Box's WM_INITDIALOG message handler calls this:
#define TRAY_ICON_ID 0xABC // <== ..our System Tray Icon Id
#define BALL_ICON_ID 0xDEF // <== ..our Balloon Tip Icon Id
#define MSG_FROM_TRAY (WM_APP + 0xDAD) // <== ..the "callback message" ID..
static NOTIFYICONDATA *NID;
static void Init_NID( HWND hDlg )
{
if ( NID = new NOTIFYICONDATA )
{
memset( NID, 0, sizeof( NOTIFYICONDATA ) );
if ( LoadIconMetric( AppInst,
(PCWSTR)MAKEINTRESOURCE( IDR_TrayIcon ),
LIM_SMALL, &NID->hIcon ) == S_OK )
{
if ( LoadIconMetric( AppInst,
(PCWSTR)MAKEINTRESOURCE( IDR_BallIcon ),
LIM_SMALL, &NID->hBalloonIcon ) == S_OK )
{
bool Opning = strcpy( NID->szTip, "My App Name" ) &&
strcpy( NID->szInfoTitle, "Hi There" ) &&
strcpy( NID->szInfo, "My notification message.." );
if ( Opning )
{
NID->uTimeout = 5000;
NID->uID = TRAY_ICON_ID;
NID->dwInfoFlags = NIIF_USER;
NID->uCallbackMessage = MSG_FROM_TRAY;
NID->cbSize = sizeof( NOTIFYICONDATA );
NID->dwState = 0;
NID->dwStateMask = NIS_HIDDEN | NIS_SHAREDICON;
return;
}
DestroyIcon( NID->hBalloonIcon );
}
DestroyIcon( NID->hIcon );
}
delete NID;
NID = NULL;
}
}
The same Dialog Box procedure also calls two other Tray-related functions, Min2SysTray(), which attempts to add the Tray Icon, display a notification, then hide the Dialog Box, and ProcMsgFromTray(), which processes messages from the Tray.
All three are invoked from the same Dialog Box procedure in the following way:
static INT_PTR CALLBACK MainDlg( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch ( uMsg )
{
case WM_SYSCOMMAND:
switch ( wParam )
{
case SC_CLOSE:
QuitThisApp( hDlg );
return( true );
case IDM_About:
DialogBoxParam( AppInst,
MAKEINTRESOURCE( IDD_About ),
hDlg, AboutDlg, 0 );
return( true );
case SC_MINIMIZE: if ( Min2SysTray( hDlg ) ) return( true );
}
break;
case MSG_FROM_TRAY:
ProcMsgFromTray( hDlg, wParam, lParam );
return( true );
case WM_INITDIALOG:
Init_NID( hDlg );
return( true );
case WM_DESTROY: PostQuitMessage( 0 );
}
return( false );
}
Where the code for my Min2SysTray() function is:
static bool Min2SysTray( HWND hDlg )
{
bool Success = false;
if ( NID )
{
NOTIFYICONDATA Ver;
memset( &Ver, 0, sizeof( NOTIFYICONDATA ) );
Ver.uID = NID->uID;
Ver.uVersion = NOTIFYICON_VERSION_4;
Ver.cbSize = sizeof( NOTIFYICONDATA );
NID->hWnd = Ver.hWnd = hDlg;
NID->uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP | NIF_SHOWTIP;
if ( Shell_NotifyIcon( NIM_ADD, NID ) && Shell_NotifyIcon( NIM_SETVERSION, &Ver ) )
{
NID->uFlags = NIF_INFO | NIF_MESSAGE | NIF_TIP | NIF_SHOWTIP;
if ( Success = Shell_NotifyIcon( NIM_MODIFY, NID ) )
ShowWindow( hDlg, SW_HIDE );
}
}
return( Success );
}
And the code for my ProcMsgFromTray() function is:
static void ProcMsgFromTray( HWND hDlg, WPARAM wParam, LPARAM lParam )
{
if ( HIWORD( lParam ) == NID->uID )
{
switch ( LOWORD( lParam ) )
{
case NIN_SELECT:
case NIN_KEYSELECT:
case WM_LBUTTONDBLCLK:
if ( NID ) Shell_NotifyIcon( NIM_DELETE, NID );
ShowWindow( hDlg, SW_SHOW );
}
}
}
And that's pretty much all of the code. Needless to say, I haven't been able to figure out what's wrong with it (yet?), if anything..
So what I need is another pair of eyes. Or two, or four.. or a thousand..
Uh! My frustration's bubbling to the surface.. please to excuse..
Anyway, if there's anyone out there who can find anything wrong with the above code, and/or can help in any other way, please respond..
Thanks in advance..
modified 16-Mar-15 23:23pm.
|
|
|
|
|
From code you posted it seems very improbable to me that it can work with memory dynamically allocated (new) for NOTIFYICONDAT. This memory is released when sub exits, while it is not reused may happen that it works, as soon it is reused and filled with data making nosense for IconNotify it will not work anymore.
The problem you mentioned is related only to services and program that starts before desktop (iexplorer) is started (that is the case of utilities wrote by the author of article you mentioned). In that case the solution is to wait for initialization to complete. You will find all info, if you need, here[^].
Making it static and changing the access to its members it works for me.
This is the amended code:
#define MSG_FROM_TRAY (WM_APP + 0xDAD) // <== ..the "callback message" ID..
static BOOL Opning = TRUE;
static NOTIFYICONDATA NID;
static void Init_NID( HWND hDlg )
{
memset( &NID, 0, sizeof( NOTIFYICONDATA ) );
if ( LoadIconMetric( AppInst,
(PCWSTR)MAKEINTRESOURCE( IDR_TrayIcon ),
LIM_SMALL, &NID.hIcon ) == S_OK )
{
if ( LoadIconMetric( AppInst,
(PCWSTR)MAKEINTRESOURCE( IDR_BallIcon ),
LIM_SMALL, &NID.hBalloonIcon ) == S_OK )
{
strcpy( NID.szTip, "My App Name" );
strcpy( NID.szInfoTitle, "Hi There" );
strcpy( NID.szInfo, "My notification message.." );
if ( Opning )
{
NID.uTimeout = 5000;
NID.uID = TRAY_ICON_ID;
NID.dwInfoFlags = NIIF_USER;
NID.uCallbackMessage = MSG_FROM_TRAY;
NID.cbSize = sizeof( NOTIFYICONDATA );
NID.dwState = 0;
NID.dwStateMask = NIS_HIDDEN | NIS_SHAREDICON;
return;
}
DestroyIcon( NID.hBalloonIcon );
}
DestroyIcon( NID.hIcon );
}
}
static BOOL Min2SysTray( HWND hDlg )
{
BOOL Success = FALSE;
NOTIFYICONDATA Ver;
memset( &Ver, 0, sizeof( NOTIFYICONDATA ) );
Ver.uID = NID.uID;
Ver.uVersion = NOTIFYICON_VERSION_4;
Ver.cbSize = sizeof( NOTIFYICONDATA );
NID.hWnd = Ver.hWnd = hDlg;
NID.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP | NIF_SHOWTIP;
if ( Shell_NotifyIcon( NIM_ADD, &NID ) && Shell_NotifyIcon( NIM_SETVERSION, &Ver ) )
{
NID.uFlags = NIF_INFO | NIF_MESSAGE | NIF_TIP | NIF_SHOWTIP;
if ( Success = Shell_NotifyIcon( NIM_MODIFY, &NID ) )
ShowWindow( hDlg, SW_HIDE );
}
return( Success );
}
static void ProcMsgFromTray( HWND hDlg, WPARAM wParam, LPARAM lParam )
{
if ( HIWORD( lParam ) == NID.uID )
{
switch ( LOWORD( lParam ) )
{
case NIN_SELECT:
case NIN_KEYSELECT:
case WM_LBUTTONDBLCLK:
Shell_NotifyIcon( NIM_DELETE, &NID );
ShowWindow( hDlg, SW_SHOW );
}
}
}
modified 16-Mar-15 19:13pm.
|
|
|
|
|