I've found the handle of a Windows Forms ToolStrip in another application.
(Window name is toolStrip1, class name is WindowsForms10.Window.8.app.0.378734a.)
Is there any way to enumerate the child buttons, find a button by caption and simulate a button click? The buttons are not child windows, so EnumChildWindows doesn't work.
Simulating a mouse click with constant coordinates on the ToolStrip itself is not a very good option as the available buttons and button captions may change.
As #Jimi suggested, the solution is to use the UI Automation Windows API. I've managed to find the button by going down in the UI automation tree of UI elements from the desktop window to the given element, matching the names of elements. Then I called Invoke on it to simulate a click.
Here my a highly unstructured "C-style" C++11 test code for demonstration purposes, in case anyone else finds it useful. You will need to link to ole32.lib and oleaut32.lib.
#include <iostream>
#include <UIAutomation.h>
bool GetChildElementByName(IUIAutomationElement * * Child,
IUIAutomationElement * Parent,
const wchar_t * Name, IUIAutomation * UIAut);
int main(int argc, char * argv[])
{
// Initialize COM
switch ( CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED) )
{
case S_OK:
break;
case S_FALSE:
CoUninitialize();
// fall through
default:
std::cout << "CoInitializeEx error.\n";
return 1;
}
// Create a CUIAutomation object and query IUIAutomation interface
IUIAutomation * uiautomation;
if ( CoCreateInstance(CLSID_CUIAutomation, nullptr, CLSCTX_INPROC_SERVER,
IID_IUIAutomation, reinterpret_cast<LPVOID *>(&uiautomation)) != S_OK )
{
std::cout << "CoCreateInstance error.\n";
CoUninitialize();
return 1;
}
// Get the desktop UI element
IUIAutomationElement * desktop;
if ( uiautomation->GetRootElement(&desktop) != S_OK )
{
std::cout << "GetRootElement error.\n";
uiautomation->Release();
CoUninitialize();
return 1;
}
// Find a button element in a window inside a toolstrip.
IUIAutomationElement * elem;
// Fix memory leak...
if
(
!GetChildElementByName(&elem, desktop, L"Thermo Scientific LabWriter V4.6", uiautomation) ||
!GetChildElementByName(&elem, elem, L"toolStrip1", uiautomation) ||
!GetChildElementByName(&elem, elem, L"Print", uiautomation)
)
{
desktop->Release();
uiautomation->Release();
CoUninitialize();
return 1;
}
desktop->Release();
// The invoke control pattern contains the Invoke method that can be used to click the button
IUIAutomationInvokePattern * invokepattern;
if ( elem->GetCurrentPattern(UIA_InvokePatternId,
reinterpret_cast<IUnknown * *>(&invokepattern)) != S_OK )
{
std::cout << "GetCurrentPattern error.\n";
elem->Release();
uiautomation->Release();
CoUninitialize();
return 1;
}
if ( invokepattern == nullptr )
{
// Possibly element is not even a button, as it should have the invoke control pattern.
std::cout << "Invoke pattern not present.\n";
elem->Release();
uiautomation->Release();
CoUninitialize();
return 1;
}
// Click the button
if ( invokepattern->Invoke() != S_OK )
{
std::cout << "Button click failed.\n";
invokepattern->Release();
elem->Release();
uiautomation->Release();
CoUninitialize();
return 1;
}
elem->Release();
invokepattern->Release();
uiautomation->Release();
CoUninitialize();
std::cout << "Done.\n";
return 0;
}
bool GetChildElementByName(IUIAutomationElement * * Child,
IUIAutomationElement * Parent,
const wchar_t * Name, IUIAutomation * UIAut)
{
// Create a condition that matches elements with name *Name
IUIAutomationCondition * cond;
// Parameter for the condition is a string-typed VARIANT containing the name.
VARIANT name;
VariantInit(&name);
name.vt = VT_BSTR;
name.bstrVal = SysAllocString(Name);
if ( name.bstrVal == nullptr )
{
std::cout << "SysAllocString error.\n";
return false;
}
if ( UIAut->CreatePropertyCondition(UIA_NamePropertyId, name, &cond) != S_OK )
{
std::cout << "CreatePropertyCondition error.\n";
VariantClear(&name);
return false;
}
VariantClear(&name);
// Find the first child element satisfying the condition.
if ( Parent->FindFirst(TreeScope_Children, cond, Child) != S_OK )
{
std::cout << "FindFirst error.\n";
cond->Release();
return false;
}
cond->Release();
if ( *Child == nullptr )
{
std::cout << "Child element \"";
std::wcout << Name;
std::cout << "\" not found.\n";
return false;
}
// Child element found
return true;
}
Related
I'm working on a macOS menubar app that locks any mouse events. What I'm trying to achieve is that after sending mouse events to the CGEventRef based callback, I cannot click anywhere (naturally) but the problem is I cannot quit the loop because of that.
Every time I need to close it, I'm switching to the Xcode app to stop the running app.
This is the main function and the events that I'm sending to the callback function;
void lockTrackpad(void) {
// For keyboard inputs, I add CGEventMaskBit(kCGEventKeyUp)| CGEventMaskBit(kCGEventKeyDown)| CGEventMaskBit(NX_SYSDEFINED)
CGEventMask mask = (
CGEventMaskBit(kCGEventMouseMoved)
| CGEventMaskBit(kCGEventLeftMouseUp)
| CGEventMaskBit(kCGEventLeftMouseDown)
| CGEventMaskBit(kCGEventRightMouseUp)
| CGEventMaskBit(kCGEventRightMouseDown)
| CGEventMaskBit(kCGEventScrollWheel)
);
eventTap = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap, kCGEventTapOptionDefault, mask, CGEventCallback_r, nil);
...
}
And this is the callback function;
CGEventRef CGEventCallback_r(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) {
CGKeyCode keycode = (CGKeyCode)CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode);
printf("Event Tap: %d\n", keycode);
if (keycode == 43) {
printf("quit the application \n");
exit(EXIT_SUCCESS);
}
return nil;
}
What I want is, for example when the loop is running, if press "control + U + L", I want to run some function to exit the loop. I believe in order to get the keyboard input, I should send the keyboard events as well but I couldn't figure out how to detect my keyboard shortcuts.
I added the keyboard bits to the mask.
The app is sandboxed.
I want to do something like this;
CGEventRef CGEventCallback_r(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) {
CGKeyCode keycode = (CGKeyCode)CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode);
// When pressing "control + U + L", call a function
if (...) {
printf("pressed control + U + L \n");
doSomething();
}
return nil;
}
I figured out like this;
CGEventRef CGEventCallback_r(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) {
if (type == kCGEventKeyDown) {
CGKeyCode keyCode = (CGKeyCode)CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode);
if (CGEventGetFlags(event) & kCGEventFlagMaskControl) {
// control key is pressed
controlKeyPressed = true;
}
if (keyCode == kVK_ANSI_U) {
// u key is pressed
uKeyPressed = true;
}
if (keyCode == kVK_ANSI_L) {
// l key is pressed
lKeyPressed = true;
}
if (controlKeyPressed && uKeyPressed && lKeyPressed) {
// doSomething();
}
return event;
} else if (type == kCGEventKeyUp) {
CGKeyCode keyCode = (CGKeyCode)CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode);
// set the variable to false just like above.
}
if (keycode == 43) {
printf("quit the application \n");
exit(EXIT_SUCCESS);
}
return nil;
}
Also, don't forget to put your variables on a global scope.
I am learning more about smart pointers in C++14.
Consider the following MWC:
#include <iostream>
#include <string>
#include <memory>
class House {
public:
House &operator=(const House &house) = default;
House(const House &house) = default;
House(): id_habitants_(nullptr), num_habitants_() {}
explicit House(size_t num_habitants) {
if (num_habitants > 0) {
num_habitants_ = num_habitants;
id_habitants_ = new int[num_habitants_];
if (id_habitants_ != nullptr) {
for (size_t id = 0; id < num_habitants_; ++id) {
id_habitants_[id] = 1;
}
}
}
}
void Print() {
if (id_habitants_ != nullptr) {
for (size_t id = 0; id < num_habitants_; ++id) {
std::cout << id_habitants_[id] << ' ';
}
std::cout << std::endl;
} else {
std::cout << "<empty>" << std::endl;
}
}
~House() {
if (id_habitants_ != nullptr) {
delete [] id_habitants_;
}
num_habitants_ = 0;
}
private:
int *id_habitants_;
size_t num_habitants_;
};
int main() {
std::cout << "Testing unique_ptr.\n" << std::endl;
std::cout << "Using a dumb House class..." << std::endl;
std::cout << "Creating House h1 with 3 habitants..." << std::endl;
House h1(3);
std::cout << "IDs of h1's 3 habitants:" << std::endl;
h1.Print();
std::cout << "Creating House h2 with 0 habitants..." << std::endl;
House h2;
std::cout << "IDs of h2's 0 habitants:" << std::endl;
h2.Print();
std::cout << "Default-assigning h1 to h2..." << std::endl;
h2 = h1;
std::cout << "IDs of h2's new 3 habitants:" << std::endl;
h2.Print();
std::cout << "Destroying h1..." << std::endl;
h1.~House();
std::cout << "IDs of h2's new 3 habitants:" << std::endl;
h2.Print();
}
Without modifying the default copy constructor and the default assignment operator for the class House, how can I ensure correct pointer behavior during assignment via smart pointers?
On a first try it seems like using std::unique_ptr would be the way to go. I could create a new class:
class SmartHouse {
public:
SmartHouse &operator=(const SmartHouse &shouse) = default;
SmartHouse(const SmartHouse &shouse) = default;
SmartHouse(): id_habitants_(nullptr), num_habitants_() {}
explicit SmartHouse(size_t num_habitants) {
if (num_habitants > 0) {
num_habitants_ = num_habitants;
id_habitants_ = std::unique_ptr<int[]>(new int[num_habitants_]);
if (id_habitants_) {
for (size_t id = 0; id < num_habitants_; ++id) {
id_habitants_[id] = 1;
}
}
}
}
void Print() {
if (id_habitants_) {
for (size_t id = 0; id < num_habitants_; ++id) {
std::cout << id_habitants_[id] << ' ';
}
std::cout << std::endl;
} else {
std::cout << "<empty>" << std::endl;
}
}
~SmartHouse() {
num_habitants_ = 0;
}
private:
std::unique_ptr<int[]> id_habitants_;
size_t num_habitants_;
};
According to this, I can't really copy one unique pointer to another. Makes sense, right? It sort of defeats the purpose of it being unique. I.e. this would not compile:
SmartHouse sh1(3);
SmartHouse sh2;
sh2 = sh1;
But I could specify a move assignment operator and have the unique_ptr<int[]> member be moved upon assignment thus transferring ownership of the pointed data to the left object upon assignment:
class SmartHouse {
SmartHouse &operator=(SmartHouse &&SmartHouse) = default;
}
...
SmartHouse sh1(3);
SmartHouse sh2;
sh2 = std::move(sh1);
sh1.~SmartHouse();
sh2.Print();
Core question: Does this make sense at all? Are there better ways to enhance assignment of pointer member variables?
Full MWE.
I have a two dimensional float array in QML. How do I get its values in C++.
I have created a class in c++ and have done the part of qmlRegisterType. The class is now accessible in QML.
Please demonstrate with a small example.
Here's what I have tried:
Header:
#include <QQuickItem>
#include <iostream>
class Controller : public QObject
{
Q_OBJECT
Q_PROPERTY(QList <QVariantList> names READ names WRITE setnames NOTIFY namesChanged)
QList <QVariantList> m_names;
public:
Controller()
{
}
~Controller() {
}
QList <QVariantList> names() const
{
return m_names;
}
public slots:
void setnames(QList <QVariantList> arg)
{
QVariantList p;
if (arg.size () > 0)
{
p = arg.first ();
std::cout << "\narg: \n" << p[0].toInt ();
}
else
std::cout << "\nqqqq " << arg.size () << "\n";
}
signals:
void namesChanged(QList <QVariantList> arg);
};
qml
import QtQuick 2.0
import FromCpp 1.0
Rectangle
{
property variant arras: [[1,2,3], [4,5,6]]
Controller
{
id: ppp
}
MouseArea
{
anchors.fill: parent
onClicked:
{
ppp.setnames(arras)
console.log(arras.length)
}
}
}
The exact output from QtCreator:
Starting /home/***/documents/test/build-junk-Desktop_Qt_5_1_0_GCC_64bit-Debug/junk...
QML debugging is enabled. Only use this in a safe environment.
2
qqqq 0
QThreadStorage: Thread 0x181e270 exited after QThreadStorage 2 destroyed
/home/***/documents/test/build-junk-Desktop_Qt_5_1_0_GCC_64bit-Debug/junk exited with code 0
///
Here, as you can see the size of the 2D array from QML is printed correctly as 2 and the size is printed 0 from c++.
Why is that happening? Please explain.
According to user1095108's answer, in order to access the internal elements of the QML's 2 Dim array passed to C++, we need to convert each row to a list as follows:
QML part:
import QtQuick 2.0
import FromCpp 1.0
Rectangle
{
property variant twoDimArray: [[1,2,3], [4,5,6]]
Controller
{
id: controllerA
}
MouseArea
{
anchors.fill: parent
onClicked:
{
controllerA.setname (twoDimArray)
}
}
}
C++ part:
void setname (QVariantList arg)
{
if (arg.size())
{
QList <QVariant> p = arg[0].toList();
std::cout << "\nRow0 0:" << p[0].toInt ();
std::cout << "\nRow0 1:" << p[1].toInt ();
std::cout << "\nRow0 2:" << p[2].toInt ();
std::cout << "\n";
QList <QVariant> p1 = arg[1].toList();
std::cout << "\nRow1 0:" << p1[0].toInt ();
std::cout << "\nRow1 1:" << p1[1].toInt ();
std::cout << "\nRow1 2:" << p1[2].toInt ();
}
}
Output:
Starting /home/.../documents/test/build-junk-Desktop_Qt_5_1_0_GCC_64bit-Debug/junk...
QML debugging is enabled. Only use this in a safe environment.
Row0 0:1
Row0 1:2
Row0 2:3
Row1 0:4
Row1 1:5
Row1 2:6/home/.../documents/test/build-junk-Desktop_Qt_5_1_0_GCC_64bit-Debug/junk exited with code 0
It is actually very simple. Javascript arrays map to QVariantLists, Javascript objects to QVariantMaps. Therefore, you are dealing with nested QVariantLists. Try this:
void setnames(QVariantList const& arg)
{
if (arg.size())
{
auto const p(arg.front().toList());
std::cout << "\narg: \n" << p.front().toInt();
}
else
std::cout << "\nqqqq " << arg.size () << "\n";
}
This is my method :
#include <QQuickItem>
#include <QDebug>
#include <QVariantList>
class Controller : public QObject
{
Q_OBJECT
Q_PROPERTY(QVariant names READ names WRITE setnames NOTIFY namesChanged)
QVariant m_names;
public:
Controller()
{
}
~Controller() {
}
QVariant names() const
{
return m_names;
}
public slots:
void setnames(QVariant arg)
{
QVariantList dim1 = arg.toList();
qDebug() << "outer dimension size" << dim1.size();
for(int i=0;i<dim1.size();++i)
{
QVariantList &dim2 = dim1.at(i).toList();
qDebug() << "inner dimension size at" << dim2.size();
}
}
signals:
void namesChanged();
};
Try this:
Somewhere in QML file:
property variant floats: [1.1, 2.2, 3.3, 4.4, 5.5, 6.6]
Includes:
#include <QtQuick/QQuickView>
#include <QQmlContext>
#include <QQmlProperty>
#include <QQuickItem>
In C++, in constructor for example:
QQuickView *view = new QQuickView();
QWidget *container = QWidget::createWindowContainer(view, ui->widget);//I show view in my widget
container->setMinimumSize(ui->widget->size());
container->setMaximumSize(ui->widget->size());
view->setSource(QUrl::fromLocalFile("pathToQMLFile"));
//starts here
QQmlProperty property(view->rootObject(), "floats");//get rootObject and set name of property
QVariantList lst = property.read().toList();//use raed method to get QVariant and convert it to list
for (int i = 0; i < lst.length(); ++i)
{
qDebug() << lst.at(i).toFloat();//show list
}
Output:
1.1
2.2
3.3
4.4
5.5
6.6
I hope my code shows main idea and you can use it in your class, because the most important job(how to get numbers) was done.
It looks like you can use QVariantList (or QList<QVariant>):
#include <QtQuick>
class Controller : public QObject
{
Q_OBJECT
Q_PROPERTY(QVariantList names READ names WRITE setnames NOTIFY namesChanged)
QVariantList m_names;
public:
Controller()
{
}
~Controller() {
}
QVariantList names() const
{
return m_names;
}
public slots:
void setnames(QVariantList arg)
{
qDebug() << arg;
}
signals:
void namesChanged(QVariantList arg);
};
#include <QApplication>
int main(int argc, char** argv)
{
QApplication app(argc, argv);
qmlRegisterType<Controller>("FromCpp", 1, 0, "Controller");
QQuickView view(QUrl(QStringLiteral("main.qml")));
view.show();
return app.exec();
}
#include "main.moc"
Output:
(QVariant(QVariantList, (QVariant(int, 1) , QVariant(int, 2) , QVariant(int, 3) ) ) , QVariant(QVariantList, (QVariant(int, 4) , QVariant(int, 5) , QVariant(int, 6) ) ) )
Im constantly getting this when I build on Qtcreator.
*** glibc detected *** /home/Exxamples/EffectivCons: realloc(): invalid pointer: 0xb6fb5414 ***
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(+0x75ee2)[0xb6603ee2]
/lib/i386-linux-gnu/libc.so.6(realloc+0x25d)[0xb660856d]
/lib/i386-linux-gnu/libc.so.6(realloc+0x273)[0xb6608583]
/opt/Qt5.1.1/5.1.1/gcc/lib/libQt5Core.so.5(_ZN9QListData7reallocEi+0x37)[0xb6906e67]
/opt/Qt5.1.1/5.1.1/gcc/lib/libQt5Core.so.5(_ZN9QListData6appendEi+0x7c)[0xb6906f4c]
/opt/Qt5.1.1/5.1.1/gcc/lib/libQt5Core.so.5(_ZN9QListData6appendEv+0x23)[0xb6906fd3]
/opt/Qt5.1.1/5.1.1/gcc/lib/libQt5Core.so.5(+0x1afa3e)[0xb6a05a3e]
/opt/Qt5.1.1/5.1.1/gcc/lib/libQt5Core.so.5(_Z21qRegisterResourceDataiPKhS0_S0_+0x216)[
This is my code, through the other questions on the website, I saw some users using malloc or realloc, but Im not using it, why am i getting an error?
#include <termios.h>
#include <string.h>
#include <stdlib.h>
#define BUFLEN 512
std::string numberToString(const int n);
void sendExpressivAnimation(int,EmoStateHandle eState);
void handleExpressivEvent(std::ostream& os, EmoEngineEventHandle expressivEvent);
bool handleUserInput();
void promptUser();
void nonblocking();
int getch();
int kbhit();
int createSocket();
int startSendPort = 30000;
struct termios initial_settings, new_settings;
int kbhit (void)
{
struct timeval tv;
fd_set rdfs;
tv.tv_sec = 0;
tv.tv_usec = 0;
FD_ZERO(&rdfs);
FD_SET (STDIN_FILENO, &rdfs);
select(STDIN_FILENO+1, &rdfs, NULL, NULL, &tv);
return FD_ISSET(STDIN_FILENO, &rdfs);
}
int main(int argc, char **argv)
{
EmoEngineEventHandle eEvent = EE_EmoEngineEventCreate();
EmoStateHandle eState = EE_EmoStateCreate();
unsigned int userID = 0;
const int CONTROL_PANEL_PORT = 3008;
bool connected = false;
if(EE_EngineRemoteConnect("127.0.0.1", CONTROL_PANEL_PORT)== EDK_OK)
{
std::cout <<"Emotiv Engine started" << std::endl;
connected = true;
}
else
{
std::cout <<"Emotiv Engine failed !"<< std::endl;
connected = false;
}
std::cout << "Type \"exit\" to quit, \"help\" to list available commands..." << std::endl;
promptUser();
int _socket;
_socket = createSocket();
if(connected)
{
nonblocking();
fflush(stdin);
while (true) {
// Handle the user input
//if (_kbhit()) {
if (!handleUserInput()) {
break;
}
//}
int state = EE_EngineGetNextEvent(eEvent);
// New event needs to be handled
if (state == EDK_OK) {
EE_Event_t eventType = EE_EmoEngineEventGetType(eEvent);
EE_EmoEngineEventGetUserId(eEvent, &userID);
switch (eventType) {
// New headset connected, create a new socket to send the animation
case EE_UserAdded:
{
std::cout << std::endl << "New user " << userID << " added, sending Expressiv animation to ";
std::cout << "127.0.0.1" << ":" << startSendPort << "..." << std::endl;
promptUser();
break;
}
// Headset disconnected, remove the existing socket
case EE_UserRemoved:
{
std::cout << std::endl << "User " << userID << " has been removed." << std::endl;
promptUser();
break;
}
// Send the Expressiv animation if EmoState has been updated
case EE_EmoStateUpdated:
{
//std::cout << "New EmoState from user " << userID << "..." << std::endl;
EE_EmoEngineEventGetEmoState(eEvent, eState);
sendExpressivAnimation(_socket,eState);
break;
}
// Handle Expressiv training event
case EE_ExpressivEvent:
{
handleExpressivEvent(std::cout, eEvent);
break;
}
default:
break;
}
}
else if (state != EDK_NO_EVENT) {
std::cout << std::endl << "Internal error in Emotiv Engine!" << std::endl;
break;
}
}
}
EE_EngineDisconnect();
EE_EmoStateFree(eState);
EE_EmoEngineEventFree(eEvent);
return 0;
}
std::string numberToString(const int n) {
char* buf;
//_itoa(n, buf, 10);
QString nStr = QString::number(n);
buf = nStr.toLocal8Bit().data();
return std::string(buf);
}
void sendExpressivAnimation(int _socket,EmoStateHandle eState) {
std::ostringstream output;
EE_ExpressivAlgo_t upperFaceType = ES_ExpressivGetUpperFaceAction(eState);
EE_ExpressivAlgo_t lowerFaceType = ES_ExpressivGetLowerFaceAction(eState);
float upperFaceAmp = ES_ExpressivGetUpperFaceActionPower(eState);
float lowerFaceAmp = ES_ExpressivGetLowerFaceActionPower(eState);
if (ES_ExpressivIsBlink(eState)) {
output << "B,";
}
if (ES_ExpressivIsLeftWink(eState)) {
output << "l,";
}
if (ES_ExpressivIsRightWink(eState)) {
output << "r,";
}
if (ES_ExpressivIsLookingRight(eState)) {
output << "R,";
}
if (ES_ExpressivIsLookingLeft(eState)) {
output << "L,";
}
if (upperFaceAmp > 0.0) {
switch (upperFaceType) {
case EXP_EYEBROW: output << "b"; break;
case EXP_FURROW: output << "f"; break;
default: break;
}
output << numberToString(static_cast<int>(upperFaceAmp*100.0f)) << ",";
}
if (lowerFaceAmp > 0.0) {
switch (lowerFaceType) {
case EXP_CLENCH: output << "G"; break;
case EXP_SMILE: output << "S"; break;
case EXP_LAUGH: output << "H"; break;
case EXP_SMIRK_LEFT: output << "sl"; break;
case EXP_SMIRK_RIGHT: output << "sr"; break;
default: break;
}
output << numberToString(static_cast<int>(lowerFaceAmp*100.0f)) << ",";
}
std::string outString = output.str();
// Remove the last comma
if (outString.length()) {
outString.resize(outString.length()-1);
}
if (!outString.length()) {
outString = std::string("neutral");
}
if(send(_socket, outString.c_str(), BUFLEN, 0)==-1)
{
std::cout<<"sending error"<<std::endl;
//exit(1);
}
}
void handleExpressivEvent(std::ostream& os, EmoEngineEventHandle expressivEvent) {
unsigned int userID = 0;
EE_EmoEngineEventGetUserId(expressivEvent, &userID);
EE_ExpressivEvent_t eventType = EE_ExpressivEventGetType(expressivEvent);
switch (eventType) {
case EE_ExpressivTrainingStarted:
{
os << std::endl << "Expressiv training for user " << userID << " STARTED!" << std::endl;
break;
}
case EE_ExpressivTrainingSucceeded:
{
os << std::endl << "Expressiv training for user " << userID << " SUCCEEDED!" << std::endl;
break;
}
case EE_ExpressivTrainingFailed:
{
os << std::endl << "Expressiv training for user " << userID << " FAILED!" << std::endl;
break;
}
case EE_ExpressivTrainingCompleted:
{
os << std::endl << "Expressiv training for user " << userID << " COMPLETED!" << std::endl;
break;
}
case EE_ExpressivTrainingDataErased:
{
os << std::endl << "Expressiv training data for user " << userID << " ERASED!" << std::endl;
break;
}
case EE_ExpressivTrainingRejected:
{
os << std::endl << "Expressiv training for user " << userID << " REJECTED!" << std::endl;
break;
}
case EE_ExpressivTrainingReset:
{
os << std::endl << "Expressiv training for user " << userID << " RESET!" << std::endl;
break;
}
case EE_ExpressivNoEvent:
default:
//## unhandled case
assert(0);
return;
}
promptUser();
}
bool handleUserInput() {
static std::string inputBuffer;
char c = getch();
if ((int)c == 10) {
std::cout << std::endl;
std::string command;
const size_t len = inputBuffer.length();
command.reserve(len);
// Convert the input to lower case first
for (size_t i=0; i < len; i++) {
command.append(1, tolower(inputBuffer.at(i)));
}
inputBuffer.clear();
bool success = parseCommand(command, std::cout);
promptUser();
return success;
}
else {
if ((int)c == 127) { // Backspace key
if (inputBuffer.length()) {
putchar('\b');
putchar(' ');
putchar('\b');
inputBuffer.erase(inputBuffer.end()-1);
}
}
else {
std::cout << c;
if(((int) c == 32) || ((int)c == 95) || (((int)c >= 97 && (int)c <=122)) || (((int)c >=48 && (int)c <= 57)))
inputBuffer.append(1,c);
}
}
return true;
}
void promptUser()
{
std::cout << "ExpressivDemo> "<<std::endl;
}
void nonblocking()
{
tcgetattr(0, &initial_settings);
new_settings = initial_settings;
new_settings.c_lflag &= ~ICANON;
new_settings.c_lflag &= ~ECHO;
//new_settings.c_lflag &= ~ISIG;
new_settings.c_cc[VMIN] = 0;
new_settings.c_cc[VTIME] = 0;
tcsetattr(0, TCSANOW, &new_settings);
}
int getch()
{
int r;
unsigned char c=0;
if((r = read(0, &c, sizeof(c))) < 0 )
{
return r;
}
else
{
return c;
}
}
int createSocket()
{
struct sockaddr_in si_other;
int s, slen = sizeof(si_other);
if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
std::cout<<"socket"<<std::endl;
memset((char *) &si_other, 0, sizeof(si_other));
si_other.sin_family = AF_INET;
si_other.sin_port = htons(startSendPort);
if (inet_aton("127.0.0.1", &si_other.sin_addr)==0)
{
std::cout<<"intet_aton failed !"<<std::endl;
//exit(1);
}
if(connect(s,(sockaddr*)&si_other,slen)==-1)
{
std::cout<<"connect failed !"<<std::endl;
// exit(1);
}
return s;
}
Your code is too big to be checked wholly. If you can reduce it to a SSCCE it will be easier for everybody.
Anyway, skimming over your code, only one thing catched my eye:
char *buf;
QString nStr = QString::number(n);
buf = nStr.toLocal8Bit().data();
return std::string(buf);
The call to toLocal8Bit() returns a temporary QByteArray and then you call its data() member function. The returned pointer is only valid during the lifetime of that temporary, that is, until the ending ;. After that the buf pointer is invalid and the next line renders undefined behavior.
You should do something like:
QString nStr = QString::number(n);
QByteArray a(nStr.toLocal8Bit());
char *buf = a.data();
return std::string(buf);
Or even better:
QString nStr = QString::number(n);
return std::string(nStr.toLocal8Bit().data());
Or just for show:
return std::string(QString::number(n).toLocal8Bit().data());
For Example:
int count;
//Code to count key presses here
sf::String String("You have pressed a key this many times: " + count );
I already know how to convert the int to a string and insert it.
Use events:
#include <SFML/Graphics.hpp>
int main()
{
// Create the main window
sf::RenderWindow window(sf::VideoMode(800, 600), "SFML window");
int count = 0;
while (window.IsOpened())
{
sf::Event event;
while (window.GetEvent(event))
{
if (event.Type == sf::Event::Closed)
window.Close();
if (event.Type == sf::Event::KeyPressed && event.Key.Code == sf::Key::A)
++count;
}
window.Clear();
// Do whatever you want with count.
window.Display();
}
return 0;
}