Хм... Странно, что не работает. А отрисовка где?
В OnPaint. Уже паправил, GetDC заменил на canvas.Handle - всё заработало.
В классической теме рисовалось, в XP нет.
Модератор: Модераторы
Хм... Странно, что не работает. А отрисовка где?
нужно както заставить TMemo.Append() не добавлять автоматом #13#10 в конец кажной строки.
А для чего, если есть свойство Text? Может, проще действительно написать функцию, убирающую #13#10?
Еще бы хотелось кроссплатформенный таймер тикающий независимо от занятости приложения. ТТimer тикает только козда приложение простаивает
/*
-----------------------------------------------------------------------------
This source file is part of OGRE
(Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/
Copyright (c) 2000-2006 Torus Knot Software Ltd
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
You may alternatively use this source under the terms of a specific version of
the OGRE Unrestricted License provided you have obtained such a license from
Torus Knot Software Ltd.
-----------------------------------------------------------------------------
*/
#ifndef __Win32Timer_H__
#define __Win32Timer_H__
#define WIN32_LEAN_AND_MEAN
#ifndef NOMINMAX
# define NOMINMAX // required to stop windows.h messing up std::min
#endif
#include <windows.h>
#include <time.h>
#include <system.hpp>
namespace Ogre
{
class Timer
{
private:
clock_t mZeroClock;
clock_t mPauseClock;
DWORD mStartTick;
DWORD mPauseTick;
LONGLONG mLastTime;
LARGE_INTEGER mStartTime;
LARGE_INTEGER mPauseTime;
LARGE_INTEGER mFrequency;
DWORD mTimerMask;
BOOL paused;
public:
/** Timer constructor. MUST be called on same thread that calls getMilliseconds() */
Timer();
~Timer();
/** Method for setting a specific option of the Timer. These options are usually
specific for a certain implementation of the Timer class, and may (and probably
will) not exist across different implementations. reset() must be called after
all setOption() calls.
@par
Current options supported are:
<ul><li>"QueryAffinityMask" (DWORD): Set the thread affinity mask to be used
to check the timer. If 'reset' has been called already this mask should
overlap with the process mask that was in force at that point, and should
be a power of two (a single core).</li></ul>
@param
strKey The name of the option to set
@param
pValue A pointer to the value - the size should be calculated by the timer
based on the key
@return
On success, true is returned.
@par
On failure, false is returned.
*/
bool setOption(const AnsiString& strKey, const void* pValue);
/** Resets timer */
void reset();
// Pause timer
void pause();
// Resume timer
void resume();
BOOL is_paused() const;
/** Returns milliseconds since initialisation or last reset */
unsigned long getMilliseconds();
/** Returns microseconds since initialisation or last reset */
unsigned long getMicroseconds();
/** Returns milliseconds since initialisation or last reset, only CPU time measured */
unsigned long getMillisecondsCPU();
/** Returns microseconds since initialisation or last reset, only CPU time measured */
unsigned long getMicrosecondsCPU();
};
}
#endif
/*
-----------------------------------------------------------------------------
This source file is part of OGRE
(Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/
Copyright (c) 2000-2006 Torus Knot Software Ltd
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
You may alternatively use this source under the terms of a specific version of
the OGRE Unrestricted License provided you have obtained such a license from
Torus Knot Software Ltd.
-----------------------------------------------------------------------------
*/
#include "OgreTimer.h"
//---------------------------------------------------------------------------
#include "Functions.h"
using namespace Ogre;
//-------------------------------------------------------------------------
Timer::Timer() : mTimerMask(0)
{
reset();
}
//-------------------------------------------------------------------------
Timer::~Timer()
{
}
//-------------------------------------------------------------------------
bool Timer::setOption( const String & key, const void * val )
{
if (key == "QueryAffinityMask")
{
// Telling timer what core to use for a timer read
DWORD newTimerMask = *static_cast <const DWORD*> ( val );
// Get the current process core mask
DWORD procMask;
DWORD sysMask;
#if _MSC_VER >= 1400 && defined (_M_X64)
GetProcessAffinityMask(GetCurrentProcess(), (PDWORD_PTR)&procMask,
(PDWORD_PTR)&sysMask);
#else
GetProcessAffinityMask(GetCurrentProcess(), &procMask, &sysMask);
#endif
// If new mask is 0, then set to default behavior, otherwise check
// to make sure new timer core mask overlaps with process core mask
// and that new timer core mask is a power of 2 (i.e. a single core)
if(( newTimerMask == 0 ) || ((( newTimerMask & procMask) != 0) &&
is2power(newTimerMask)))
{
mTimerMask = newTimerMask;
return true;
}
}
return false;
}
//-------------------------------------------------------------------------
void Timer::reset()
{
// Get the current process core mask
DWORD procMask;
DWORD sysMask;
#if _MSC_VER >= 1400 && defined (_M_X64)
GetProcessAffinityMask(GetCurrentProcess(), (PDWORD_PTR)&procMask,
(PDWORD_PTR)&sysMask);
#else
GetProcessAffinityMask(GetCurrentProcess(), &procMask, &sysMask);
#endif
// If procMask is 0, consider there is only one core available
// (using 0 as procMask will cause an infinite loop below)
if (procMask == 0) procMask = 1;
// Find the lowest core that this process uses
if (mTimerMask == 0)
{
mTimerMask = 1;
while ((mTimerMask & procMask) == 0)
{
mTimerMask <<= 1;
}
}
HANDLE thread = GetCurrentThread();
// Set affinity to the first core
DWORD oldMask = SetThreadAffinityMask(thread, mTimerMask);
// Get the constant frequency
QueryPerformanceFrequency(&mFrequency);
// Query the timer
QueryPerformanceCounter(&mStartTime);
mStartTick = GetTickCount();
// Reset affinity
SetThreadAffinityMask(thread, oldMask);
mLastTime = 0;
mZeroClock = clock();
paused = false;
}
//-------------------------------------------------------------------------
void Timer::pause()
{
// Запоминаю время паузы
// Get the current process core mask
DWORD procMask;
DWORD sysMask;
#if _MSC_VER >= 1400 && defined (_M_X64)
GetProcessAffinityMask(GetCurrentProcess(), (PDWORD_PTR)&procMask,
(PDWORD_PTR)&sysMask);
#else
GetProcessAffinityMask(GetCurrentProcess(), &procMask, &sysMask);
#endif
// If procMask is 0, consider there is only one core available
// (using 0 as procMask will cause an infinite loop below)
if (procMask == 0) procMask = 1;
// Find the lowest core that this process uses
if (mTimerMask == 0)
{
mTimerMask = 1;
while ((mTimerMask & procMask) == 0)
{
mTimerMask <<= 1;
}
}
HANDLE thread = GetCurrentThread();
// Set affinity to the first core
DWORD oldMask = SetThreadAffinityMask(thread, mTimerMask);
// Get the constant frequency
QueryPerformanceFrequency(&mFrequency);
// Query the timer
QueryPerformanceCounter(&mPauseTime);
mPauseTick = GetTickCount();
// Reset affinity
SetThreadAffinityMask(thread, oldMask);
mLastTime = 0;
mPauseClock = clock();
paused = true;
}
//-------------------------------------------------------------------------
void Timer::resume()
{
// Добавляю к начальному времени промежуток, прошедший с момента паузы
clock_t mResumeClock;
DWORD mResumeTick;
LARGE_INTEGER mResumeTime;
// Get the current process core mask
DWORD procMask;
DWORD sysMask;
#if _MSC_VER >= 1400 && defined (_M_X64)
GetProcessAffinityMask(GetCurrentProcess(), (PDWORD_PTR)&procMask,
(PDWORD_PTR)&sysMask);
#else
GetProcessAffinityMask(GetCurrentProcess(), &procMask, &sysMask);
#endif
// If procMask is 0, consider there is only one core available
// (using 0 as procMask will cause an infinite loop below)
if (procMask == 0) procMask = 1;
// Find the lowest core that this process uses
if (mTimerMask == 0)
{
mTimerMask = 1;
while ((mTimerMask & procMask) == 0)
{
mTimerMask <<= 1;
}
}
HANDLE thread = GetCurrentThread();
// Set affinity to the first core
DWORD oldMask = SetThreadAffinityMask(thread, mTimerMask);
// Get the constant frequency
QueryPerformanceFrequency(&mFrequency);
// Query the timer
QueryPerformanceCounter(&mResumeTime);
mStartTime.QuadPart += mResumeTime.QuadPart - mPauseTime.QuadPart;
mResumeTick = GetTickCount();
mStartTick += mResumeTick - mPauseTick;
// Reset affinity
SetThreadAffinityMask(thread, oldMask);
mLastTime = 0;
mResumeClock = clock();
mZeroClock += mResumeClock - mPauseClock;
paused = false;
}
//-------------------------------------------------------------------------
BOOL Timer::is_paused() const
{
return(paused);
}
//-------------------------------------------------------------------------
unsigned long Timer::getMilliseconds()
{
LARGE_INTEGER curTime;
HANDLE thread = GetCurrentThread();
// Set affinity to the first core
DWORD oldMask = SetThreadAffinityMask(thread, mTimerMask);
// Query the timer
QueryPerformanceCounter(&curTime);
// Reset affinity
SetThreadAffinityMask(thread, oldMask);
LONGLONG newTime = curTime.QuadPart - mStartTime.QuadPart;
// scale by 1000 for milliseconds
unsigned long newTicks = (unsigned long)
(1000 * newTime / mFrequency.QuadPart);
// detect and compensate for performance counter leaps
// (surprisingly common, see Microsoft KB: Q274323)
unsigned long check = GetTickCount() - mStartTick;
signed long msecOff = (signed long)(newTicks - check);
if (msecOff < -100 || msecOff > 100)
{
// We must keep the timer running forward :)
LONGLONG adjust =
min(msecOff * mFrequency.QuadPart / 1000, newTime - mLastTime);
mStartTime.QuadPart += adjust;
newTime -= adjust;
// Re-calculate milliseconds
newTicks = (unsigned long)(1000 * newTime / mFrequency.QuadPart);
}
// Record last time for adjust
mLastTime = newTime;
return newTicks;
}
//-------------------------------------------------------------------------
unsigned long Timer::getMicroseconds()
{
LARGE_INTEGER curTime;
HANDLE thread = GetCurrentThread();
// Set affinity to the first core
DWORD oldMask = SetThreadAffinityMask(thread, mTimerMask);
// Query the timer
QueryPerformanceCounter(&curTime);
// Reset affinity
SetThreadAffinityMask(thread, oldMask);
LONGLONG newTime = curTime.QuadPart - mStartTime.QuadPart;
// get milliseconds to check against GetTickCount
unsigned long newTicks =
(unsigned long)(1000 * newTime / mFrequency.QuadPart);
// detect and compensate for performance counter leaps
// (surprisingly common, see Microsoft KB: Q274323)
unsigned long check = GetTickCount() - mStartTick;
signed long msecOff = (signed long)(newTicks - check);
if (msecOff < -100 || msecOff > 100)
{
// We must keep the timer running forward :)
LONGLONG adjust =
min(msecOff * mFrequency.QuadPart / 1000, newTime - mLastTime);
mStartTime.QuadPart += adjust;
newTime -= adjust;
}
// Record last time for adjust
mLastTime = newTime;
// scale by 1000000 for microseconds
unsigned long newMicro =
(unsigned long)(1000000 * newTime / mFrequency.QuadPart);
return newMicro;
}
//-------------------------------------------------------------------------
unsigned long Timer::getMillisecondsCPU()
{
if (paused) resume();
clock_t newClock = clock();
return(unsigned long)((float)(newClock - mZeroClock) /
((float)CLOCKS_PER_SEC / 1000.0 ));
}
//-------------------------------------------------------------------------
unsigned long Timer::getMicrosecondsCPU()
{
if (paused) resume();
clock_t newClock = clock();
return(unsigned long)((float)(newClock - mZeroClock) /
((float)CLOCKS_PER_SEC / 1000000.0 )) ;
}
//-------------------------------------------------------------------------
//---------------------------------------------------------------------------
void __fastcall TProgramLogic::MainProc()
{
while (FTimerEnabled)
{
FCounter = FTimer.getMilliseconds();
if (FNSEventEnabled && FNSEventPeriod)
{
if (((FCounter - FNSEventStartTime) / 1000) >= FNSEventPeriod)
{
FNSEventStartTime = FCounter;
FEventMechanism->GenerateEvent(evtNS);
}
}
if ((!FSecondmeterMode && (FCounter >= FMaximumMs)) /* ||
((FMaximumPeriod) && (FCurrentPeriod >= FMaximumPeriod))*/
)
{
// Проверка на число периодов делается в AddToLog
PauseTimer(ttcAuto);
}
Application->ProcessMessages();
Repaint();
}
}
...
FTimer.reset();
MainProc();
function timeSetEvent(uDelay, uReolution: UINT; lpTimeProc: GDBPointer;dwUser: DWord; fuEvent: UINT): GDBInteger; stdcall; external 'winmm';
function timeKillEvent(uID: UINT): GDBInteger; stdcall; external 'winmm';
Спасибо, но RDTSC для меня будет лишним. Городить потоки под таймер - к счастью я не пишу программу управления термоядерными реактороми))
в винде пользовался:
Сегодня наконецто ZCAD скомпилировался и запустился под linux`ом, много чего зарезано, но всеравно приятно...
спасибо CASEзависимости! нафига она нужна и как с ней бороться? запарился руками править исходники и рантайм файлы.
как получить версию файла?
Плохая идея. Мультимедийные таймеры ненадёжны. Они отстают очень сильно, при загруженной системе.
Что есть CASE зависимость?
Я не знаю что такое TFileVersionInfo. Но могу предположить, что если это получение VersionInfo, то под linux это работать, скорее всего, не будет.
VersionInfo - это хранящееся в ресурсах данные о версии PE файла. Структуры ELF я совсем не знаю, но полагаю, что VersionInfo туда не добавляется.
Может, возможно и без него обойтись?
...
{$IFDEF WINDOWS}
Reader:=TWinPEImageResourceReader.Create;
{$ENDIF}
{$IFDEF LINUX}
Reader:=TElfResourceReader.Create;
{$ENDIF}
...
uppanel.align:=alClient;
spliter.allign:=alBottom;
downpanel.allign:=alBottom;
uppanel.align:=alClient;
spliter.align:=alBottom;
downpanel.align:=alBottom;
Spliter.Top := 0;
Сейчас этот форум просматривают: Yandex [Bot] и гости: 220