Here's the problem:
I wrote a program to receive data from a StockClient.
When I use DDESpy, I can see s message such as
Time:xxxx hwndTo=0xe00b0 Message(Posted)=Data:<br>
hwndFrom=0x1f06dc, status=2000(fRelease ) fmt=0x1("CF_TEXT")<br>
Data= "value"<br>
Item= "xxxxx"<br>
But my ddecallback function doesn't work (occasionally it can work), why?
DdeInitialize( &_dde_inst, dde_callback, APPCMD_CLIENTONLY/*|CBF_FAIL_ALLSVRXACTIONS*/, 0 );
HSZ _server = DdeCreateStringHandle ( _dde_inst, "DDEServer", CP_WINANSI );
if( !_server )
return -1;
HSZ _topic = DdeCreateStringHandle( _dde_inst, "TOPIC1", CP_WINANSI );
HCONV _conv = DdeConnect( _dde_inst, _server, _topic, NULL );
if( !_conv )
return -1;
for( int i = 0; i < ITEM_NUM; ++i )
{
HSZ _item = DdeCreateStringHandle( _dde_inst, _list[i], CP_WINANSI );
if( _item )
{
DWORD _result;
HDDEDATA _data = DdeClientTransaction( NULL, NULL, _conv, _item, CF_TEXT, XTYP_ADVSTART, TIMEOUT_ASYNC, &_result );
UINT _error = DdeGetLastError(_dde_inst );
DdeFreeStringHandle( _dde_inst, _item );
int _reserve = DMLERR_NO_ERROR;
if( _error != 0 )
{
fprintf( stdout, "dde error = %d\n", _error );
continue;
}
}
}
Related
#include <SoftwareSerial.h>
SoftwareSerial GSM(9, 10); // RX, TX
int sensor=5;
enum _parseState {
PS_DETECT_MSG_TYPE,
PS_IGNORING_COMMAND_ECHO,
PS_HTTPACTION_TYPE,
PS_HTTPACTION_RESULT,
PS_HTTPACTION_LENGTH,
PS_HTTPREAD_LENGTH,
PS_HTTPREAD_CONTENT
};
byte parseState = PS_DETECT_MSG_TYPE;
char buffer[80];
byte pos = 0;
int contentLength = 0;
void resetBuffer() {
memset(buffer, 0, sizeof(buffer));
pos = 0;
}
void sendGSM(const char* msg, int waitMs = 500) {
GSM.println(msg);
delay(waitMs);
while(GSM.available()) {
parseATText(GSM.read());
}
}
void setup()
{
GSM.begin(9600);
Serial.begin(9600);
sendGSM("AT+SAPBR=3,1,\"APN\",\"zongwap\"");
sendGSM("AT+SAPBR=1,1",300);
sendGSM("AT+HTTPINIT");
sendGSM("AT+HTTPPARA=\"CID\",1");
sendGSM("AT+HTTPPARA=\"URL\",\"http://afridiofkh.000webhostapp.com?
sensor1="" + sensor + ""\"""");
sendGSM("AT+HTTPACTION=0");
}
void loop()
{
while(GSM.available()) {
parseATText(GSM.read());
}
}
void parseATText(byte b) {
buffer[pos++] = b;
if ( pos >= sizeof(buffer) )
resetBuffer(); // just to be safe
/*
// Detailed debugging
Serial.println();
Serial.print("state = ");
Serial.println(state);
Serial.print("b = ");
Serial.println(b);
Serial.print("pos = ");
Serial.println(pos);
Serial.print("buffer = ");
Serial.println(buffer);*/
switch (parseState) {
case PS_DETECT_MSG_TYPE:
{
if ( b == '\n' )
resetBuffer();
else {
if ( pos == 3 && strcmp(buffer, "AT+") == 0 ) {
parseState = PS_IGNORING_COMMAND_ECHO;
}
else if ( b == ':' ) {
//Serial.print("Checking message type: ");
//Serial.println(buffer);
if ( strcmp(buffer, "+HTTPACTION:") == 0 ) {
Serial.println("Received HTTPACTION");
parseState = PS_HTTPACTION_TYPE;
}
else if ( strcmp(buffer, "+HTTPREAD:") == 0 ) {
Serial.println("Received HTTPREAD");
parseState = PS_HTTPREAD_LENGTH;
}
resetBuffer();
}
}
}
break;
case PS_IGNORING_COMMAND_ECHO:
{
if ( b == '\n' ) {
Serial.print("Ignoring echo: ");
Serial.println(buffer);
parseState = PS_DETECT_MSG_TYPE;
resetBuffer();
}
}
break;
case PS_HTTPACTION_TYPE:
{
if ( b == ',' ) {
Serial.print("HTTPACTION type is ");
Serial.println(buffer);
parseState = PS_HTTPACTION_RESULT;
resetBuffer();
}
}
break;
case PS_HTTPACTION_RESULT:
{
if ( b == ',' ) {
Serial.print("HTTPACTION result is ");
Serial.println(buffer);
parseState = PS_HTTPACTION_LENGTH;
resetBuffer();
}
}
break;
case PS_HTTPACTION_LENGTH:
{
if ( b == '\n' ) {
Serial.print("HTTPACTION length is ");
Serial.println(buffer);
// now request content
GSM.print("AT+HTTPREAD=0,");
GSM.println(buffer);
parseState = PS_DETECT_MSG_TYPE;
resetBuffer();
}
}
break;
case PS_HTTPREAD_LENGTH:
{
if ( b == '\n' ) {
contentLength = atoi(buffer);
Serial.print("HTTPREAD length is ");
Serial.println(contentLength);
Serial.print("HTTPREAD content: ");
parseState = PS_HTTPREAD_CONTENT;
resetBuffer();
}
}
break;
case PS_HTTPREAD_CONTENT:
{
// for this demo I'm just showing the content bytes in the serial monitor
Serial.write(b);
contentLength--;
if ( contentLength <= 0 ) {
// all content bytes have now been read
parseState = PS_DETECT_MSG_TYPE;
resetBuffer();
}
}
break;
}
}
i even don't understand the code but i get the idea and when i am trying to post the data to web its not working i don't know what's wrong with it
i am getting web content back but i can't post data to the web
i tried both get and post method non of them brought luck to me
The http request you made in your code has some mistakes.You can't request from arduino as you did.
When using 000webhost for database the best way is to make use of PHP.You can upload PHP files by selecting File Manager and then select "Upload files now" .In that there is a folder named "public_html" ,it's where the PHP codes are to be uploaded.
Now here is what you want to do.You want to create a PHP code which would perform the insertion operation to the database when the URL of this php code is requested.Then you can request this link from arduino for performing insertion.
The PHP code is ( Please provide your username,password,dbname,table name,column name in the provided locations of the code and upload it as i said above) :
<?php
$servername = "localhost";
$username = "provide your username here";
$password = "password here";
$dbname = "database name here";
// Create connection
$conn = mysqli_connect($servername, $username, $password, $dbname);
// Check connection
if (!$conn) {
die("Connection failed: " . mysqli_connect_error());
}
$sql = "INSERT INTO table_name (column_name) VALUES ('".mysqli_real_escape_string($conn,$_GET['sensor1'])."')";
if (mysqli_query($conn, $sql)) {
echo "New record created successfully";
} else {
echo "Error: " . $sql . "<br>" . mysqli_error($conn);
}
mysqli_close($conn);
?>
Obtain the URL of the uploaded PHP code (right click uploaded file and click view , then copy URL in the browser). You can use it in your Arduino sketch.
Your arduino code should look like ( URL in this sketch is incomplete replace it with one obtained as i said above [ http://afridiofkh.000webhostapp.com/phpfilename.php this is the one to be replaced.starting from http till ? mark is to be replaced] ) :
#include <SoftwareSerial.h>
SoftwareSerial GSM(9, 10); // RX, TX
int sensor=5;
enum _parseState {
PS_DETECT_MSG_TYPE,
PS_IGNORING_COMMAND_ECHO,
PS_HTTPACTION_TYPE,
PS_HTTPACTION_RESULT,
PS_HTTPACTION_LENGTH,
PS_HTTPREAD_LENGTH,
PS_HTTPREAD_CONTENT
};
byte parseState = PS_DETECT_MSG_TYPE;
char buffer[130],url[130]; //adjust as your url length
byte pos = 0;
int contentLength = 0;
void resetBuffer() {
memset(buffer, 0, sizeof(buffer));
pos = 0;
}
void sendGSM(const char* msg, int waitMs = 500) {
GSM.println(msg);
delay(waitMs);
while(GSM.available()) {
parseATText(GSM.read());
}
}
void setup()
{
GSM.begin(9600);
Serial.begin(9600);
sendGSM("AT+SAPBR=3,1,\"APN\",\"zongwap\"");
sendGSM("AT+SAPBR=1,1",300);
sendGSM("AT+HTTPINIT");
sendGSM("AT+HTTPPARA=\"CID\",1");
sprintf(url, "AT+HTTPPARA=\"URL\",\"http://afridiofkh.000webhostapp.com/phpfilename.php?sensor1=%d\"",sensor);
sendGSM(url);
sendGSM("AT+HTTPACTION=0");
}
void loop()
{
while(GSM.available()) {
parseATText(GSM.read());
}
}
void parseATText(byte b) {
buffer[pos++] = b;
if ( pos >= sizeof(buffer) )
resetBuffer(); // just to be safe
/*
// Detailed debugging
Serial.println();
Serial.print("state = ");
Serial.println(state);
Serial.print("b = ");
Serial.println(b);
Serial.print("pos = ");
Serial.println(pos);
Serial.print("buffer = ");
Serial.println(buffer);*/
switch (parseState) {
case PS_DETECT_MSG_TYPE:
{
if ( b == '\n' )
resetBuffer();
else {
if ( pos == 3 && strcmp(buffer, "AT+") == 0 ) {
parseState = PS_IGNORING_COMMAND_ECHO;
}
else if ( b == ':' ) {
//Serial.print("Checking message type: ");
//Serial.println(buffer);
if ( strcmp(buffer, "+HTTPACTION:") == 0 ) {
Serial.println("Received HTTPACTION");
parseState = PS_HTTPACTION_TYPE;
}
else if ( strcmp(buffer, "+HTTPREAD:") == 0 ) {
Serial.println("Received HTTPREAD");
parseState = PS_HTTPREAD_LENGTH;
}
resetBuffer();
}
}
}
break;
case PS_IGNORING_COMMAND_ECHO:
{
if ( b == '\n' ) {
Serial.print("Ignoring echo: ");
Serial.println(buffer);
parseState = PS_DETECT_MSG_TYPE;
resetBuffer();
}
}
break;
case PS_HTTPACTION_TYPE:
{
if ( b == ',' ) {
Serial.print("HTTPACTION type is ");
Serial.println(buffer);
parseState = PS_HTTPACTION_RESULT;
resetBuffer();
}
}
break;
case PS_HTTPACTION_RESULT:
{
if ( b == ',' ) {
Serial.print("HTTPACTION result is ");
Serial.println(buffer);
parseState = PS_HTTPACTION_LENGTH;
resetBuffer();
}
}
break;
case PS_HTTPACTION_LENGTH:
{
if ( b == '\n' ) {
Serial.print("HTTPACTION length is ");
Serial.println(buffer);
// now request content
GSM.print("AT+HTTPREAD=0,");
GSM.println(buffer);
parseState = PS_DETECT_MSG_TYPE;
resetBuffer();
}
}
break;
case PS_HTTPREAD_LENGTH:
{
if ( b == '\n' ) {
contentLength = atoi(buffer);
Serial.print("HTTPREAD length is ");
Serial.println(contentLength);
Serial.print("HTTPREAD content: ");
parseState = PS_HTTPREAD_CONTENT;
resetBuffer();
}
}
break;
case PS_HTTPREAD_CONTENT:
{
// for this demo I'm just showing the content bytes in the serial monitor
Serial.write(b);
contentLength--;
if ( contentLength <= 0 ) {
// all content bytes have now been read
parseState = PS_DETECT_MSG_TYPE;
resetBuffer();
}
}
break;
}
}
This would perform the insertion operation as you need to.PHP is easy as it can be used to extend the operations.
When I am selecting items in treewidget and then clicked on delete button then is is just deleting top most item only from treewidget
Can you correct this code?
This function is calling in connect statement while clicking on button
void TableDockWidget::deleteGroup() {
QTreeWidgetItem *item = treeWidget->currentItem();
QTreeWidgetItem* nextItem = treeWidget->itemBelow(item);
if ( item == NULL ) return;
PeakGroup* group = getSelectedGroup(); //this function is using to //select items from treewidget
if ( group == NULL ) return;
PeakGroup* parentGroup = group->parent;
if ( parentGroup == NULL ) { //top level item
deleteGroup(group); //this is using to delete group
} else if ( parentGroup && parentGroup->childCount() ) { //this a child item
if ( parentGroup->deleteChild(group) ) {
QTreeWidgetItem* parentItem = item->parent();
if ( parentItem ) {
parentItem->removeChild(item);
delete(item);
}
}
}
//show NextItem
if(nextItem) treeWidget->setCurrentItem(nextItem,0);
return;
}
//here, code of function which is selecting items.
PeakGroup* TableDockWidget::getSelectedGroup() {
QTreeWidgetItem *item = treeWidget->currentItem();
if (!item) return NULL;
QVariant v = item->data(0,Qt::UserRole);
PeakGroup* group = v.value<PeakGroup*>();
if ( group != NULL ) { return group; }
return NULL;
}
// code of function which is deleting group
void TableDockWidget::deleteGroup(PeakGroup *groupX) {
qDebug() << "TableDockWidget::deleteGroup()";
if(!groupX) return;
int pos=-1;
for(int i=0; i < allgroups.size(); i++) {
if ( &allgroups[i] == groupX ) {
pos=i; break;
}
}
if (pos == -1) return;
//qDebug() << "Delete pos=" << pos;
QTreeWidgetItemIterator it(treeWidget);
while (*it) {
QTreeWidgetItem* item = (*it);
if (item->isHidden()) { ++it; continue; }
QVariant v = item->data(0,Qt::UserRole);
PeakGroup* group = v.value<PeakGroup*>();
if ( group != NULL and group == groupX) {
item->setHidden(true);
//Deleteing
allgroups.erase(allgroups.begin()+pos);
int posTree = treeWidget->indexOfTopLevelItem(item);
if (posTree != -1) treeWidget->takeTopLevelItem(posTree);
break;
}
++it;
}
for(unsigned int i = 0; i < allgroups.size(); i++) {
allgroups[i].groupId = i + 1;
}
updateTable();
_mainwindow->getEicWidget()->replotForced();
}
PeakGroup* TableDockWidget::getSelectedGroup() {
PeakGroup* group;
QList<QTreeWidgetItem*>selected = treeWidget->selectedItems();
if(selected.size() == 0) return NULL;
Q_FOREACH (QTreeWidgetItem* item, selected) {
QVariant v = item->data(0,Qt::UserRole);
group = v.value<PeakGroup*>();
item->setHidden(true);
}
if ( group != NULL ) { return group; }
else
return NULL;
}
My requirement is to play 16 bit, 22KHz linear PCM data to audioout using alsa API. I have added 2 section of code which i have written to configure ALSA and audioout wrapper which writes 2048 frames using write API.
Issue : Getting distorted noise and consuming available frames very quickly
I am configuring ALSA using below api's.
//opening audio handle
if ((err = snd_pcm_open (&rsettings->ppcm_handle, name, SND_PCM_STREAM_PLAYBACK, 0)) < 0)
{
return -1;
}
if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0)
{
return -1;
}
if ((err = snd_pcm_hw_params_any (rsettings->ppcm_handle, hw_params)) < 0)
{
return -1;
}
//setting interleaved mode
if ((err = snd_pcm_hw_params_set_access (rsettings->ppcm_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
{
return -1;
}
//setting bit depth to 2 byte
if ((err = snd_pcm_hw_params_set_format (rsettings->ppcm_handle, hw_params, SND_PCM_FORMAT_S16_LE) ) < 0)
{
return -1;
}
//Setting sample rate to 22050 Hz
if ((err = snd_pcm_hw_params_set_rate(rsettings->ppcm_handle, hw_params, 22050, 0 ) ) < 0 )
{
return -1;
}
//setting number of channels to 1
if ((err = snd_pcm_hw_params_set_channels (rsettings->ppcm_handle, hw_params, 1 ) ) < 0)
{
return -1;
}
snd_pcm_uframes_t frame_size = 1024;
if(( err = snd_pcm_hw_params_set_period_size_near(rsettings->ppcm_handle, hw_params, &frame_size, 0 ) ) < 0 )
{
printf("\n cannot set size");
return -1;
}
// setting number of period to 1
if ((err = snd_pcm_hw_params_set_periods(rsettings->ppcm_handle, hw_params, 1, 1 ) ) < 0)
{
return -1;
}
frame_size = 2048;
//setting buffer size to 2048
if ((err = snd_pcm_hw_params_set_buffer_size_near(rsettings->ppcm_handle, hw_params, &frame_size) ) < 0)
{
return -1;
}
if ((err = snd_pcm_nonblock (rsettings->ppcm_handle, 0 ) ) < 0)
{
return -1;
}
if ( (err = snd_pcm_hw_params (rsettings->ppcm_handle, hw_params)) < 0)
{
return -1;
}
snd_pcm_hw_params_free (hw_params);
if ((err = snd_pcm_prepare (rsettings->ppcm_handle)) < 0)
{
return -1;
}
I have audioout API using POLLING as below
noOfFrames = 2024
while( noOfFrames > 0 )
{
if( 0 > ( poll( descriptors, pollDescriptorCount, 500 ) ) )
{
printf("error polling for data");
}
else
{
printf("\nPoll Unblocked");
if( 0 > ( retVal = snd_pcm_poll_descriptors_revents( rsettings->ppcm_handle, descriptors, pollDescriptorCount, &pollEvent ) ) )
{
printf("\nError getting poll events, return value : %d", retVal);
break;
}
else
{
frames = snd_pcm_avail_update( rsettings->ppcm_handle );
printf("\nAvailable channel frames = %d",frames );
if( frames < 0 )
{
if( frames == -EPIPE )
{
snd_pcm_prepare( rsettings->ppcm_handle );
}
else if( frames == -ESTRPIPE )
{
while (-EAGAIN == snd_pcm_resume( rsettings->ppcm_handle ) )
usleep(2000);
}
else
{
snd_pcm_prepare( rsettings->ppcm_handle);
}
}
else
{
if( frames >= noOfFrames )
{
if ((framesWritten = snd_pcm_writei(rsettings->ppcm_handle, &pBuffer, noOfFrames)) > 0 )
{
printf("\nNo of frames written : %d",framesWritten);
noOfFrames = noOfFrames - framesWritten;
free(descriptors);
}
else if( framesWritten < 0 )
{
if( framesWritten == -EPIPE )
{
snd_pcm_prepare( rsettings->ppcm_handle );
}
else if( framesWritten == -ESTRPIPE )
{
while (-EAGAIN == snd_pcm_resume( rsettings->ppcm_handle ))
usleep(2000);
}
else
{
snd_pcm_prepare( rsettings->ppcm_handle );
}
}
}
else
{
if ( ( framesWritten = snd_pcm_writei(rsettings->ppcm_handle, &pBuffer, frames ) ) > 0 )
{
printf("\nNo of frames written : %d",framesWritten);
noOfFrames = noOfFrames - framesWritten;
free(descriptors);
}
else if( framesWritten < 0 )
{
if( framesWritten == -EPIPE )
{
snd_pcm_prepare( rsettings->ppcm_handle );
}
else if( framesWritten == -ESTRPIPE )
{
while (-EAGAIN == snd_pcm_resume( rsettings->ppcm_handle ))
usleep(2000);
}
else
{
snd_pcm_prepare( rsettings->ppcm_handle );
}
}
}
}
}
}
}
Can some tell where i am going wrong.
Polling to fill Audio Unit buffers with just the requested amount of data will not work. You have to use the Audio Unit callback routines (which the OS calls using a lower latency real-time thread) to fill the audio buffers.
You can poll to pre-fill a lock-free circular fifo with a sufficient amount of audio samples for the Audio Unit callbacks to copy from.
In a code I have 2 CString which contain a part of version number,
First exe contain version 1.1234.3.1 and the second exe has version 1.2.3.1.
Code should be such that
Suppose
CString MinVreg,MinFref;
if(MinVreg<MinFref) //when MinVreg="1234" and MinFref="2"
{
//it enters in if loop.
//Update registry
}
elseif(MinVreg>MinFref)
{
//Show message box..
}
I think the operator check only first digit.So please tell me how to compare it as a number
You have to parse the strings to represent a version as an integer array, then perform a lexicographic compare.
bool ParseVersionString(unsigned digits[4], const CString& i_version)
{
return sscanf(i_version, "%d.%d.%d.%d", &digits[0], &digits[1],
&digits[2], &digits[3]) == 4;
}
int CompareVersions(unsigned ver1[4], unsigned ver2[4])
{
for (int i = 0; i != 4; ++i)
{
if (ver1[i] < ver2[i])
return -1;
if (ver1[i] > ver2[i])
return 1;
}
return 0;
}
Usage:
CString MinVreg("1.1234.3.1"), MinFref("1.2.3.1");
unsigned ver1[4], ver2[4];
if (ParseVersionString(ver1, MinVreg) &&
ParseVersionString(ver2, MinFref) &&
CompareVersions(ver1, ver2) < 0)
{
//Update registry
}
Try this:
if ( atoi((char*)(LPCTSTR)MinVreg) < atoi((char*)(LPCTSTR)MinFref)
{
//Do the Stuff
}
You should use strstr function to check if the character is present or not.
if( NULL != strstr(MinVreg, MinFref) )
{
//enter the loop
}
EDIT::
If you want to compare them as int, you need to convert them to int.
if( atoi(MinVreg) < atoi(MinFref) )
{
//MinVreg < MinFref, Do something
}
elseif( atoi(MinVreg) > atoi(MinFref) )
{
//MinVreg > MinFref, Do something
}
else
{
//MinVreg = MinFref, Do something
}
UPDATE:: After question data edited to MinVreg = 1.1234.3.1 and MinFref = 1.2.3.1
int a ;
a = strcmp( MinVreg, MinFref ) ;
if( a < 0 )
{
//MinVreg < MinFref, Do something
}
elseif( a > 0 )
{
//MinVreg > MinFref, Do something
}
else
{
//MinVreg = MinFref, Do something
}
Why use strings in the first place? Here's how I keep track of versions.
BOOL GetProductVersion(VS_FIXEDFILEINFO &fixedFileInfo, LPCTSTR szFileName)
{
DWORD dwHandle = 0;
DWORD dwLen = GetFileVersionInfoSize(szFileName, &dwHandle);
if (dwLen == 0)
return FALSE;
LPSTR lpVI = new CHAR[dwLen];
if (!lpVI)
return FALSE;
ZeroMemory(lpVI, dwLen);
GetFileVersionInfo(szFileName, dwHandle, dwLen, lpVI);
DWORD dwBufSize;
VS_FIXEDFILEINFO* lpFFI;
if (VerQueryValue(lpVI, "\\", (LPVOID*)&lpFFI, (PUINT)&dwBufSize))
{
fixedFileInfo = *lpFFI;
delete [] lpVI;
return TRUE;
}
delete [] lpVI;
return FALSE;
}
CString GetProductVersionAsString(LPCTSTR szFileName)
{
CString version;
VS_FIXEDFILEINFO ffi;
if (GetProductVersion(ffi, szFileName))
{
stringstream ss;
ss << HIWORD(ffi.dwProductVersionMS) << '.';
ss << LOWORD(ffi.dwProductVersionMS) << '.';
ss << HIWORD(ffi.dwProductVersionLS);
UINT beta = LOWORD(ffi.dwProductVersionLS);
if (beta)
ss << " beta" << beta;
version = ss.str().c_str();
}
return version;
}
DWORD GetProductVersionAsInteger(LPCTSTR szFileName)
{
DWORD version = 0;
VS_FIXEDFILEINFO ffi;
if (GetProductVersion(ffi, szFileName))
{
// Apply your number logic here!
// This code is suitable for x.y.z
version += 100 * HIWORD(ffi.dwProductVersionMS);
version += 10 * LOWORD(ffi.dwProductVersionMS);
version += HIWORD(ffi.dwProductVersionLS);
}
return version;
}
Hence, "1.0.2" becomes 102. Obviously, larger version numbers need other multipliers.
I'm making a blackberry app, I just want to know how can I align the buttons in such a way that 1 is extreme right and the picture is extreme left. I have tried horizontal manager but it's not supporting Field.Field_RIGHT and Field.Field_Left.
try this-
HorizontalFieldManager hfm=new HorizontalFieldManager(FIELD_HCENTER);
ButtonField left=new ButtonField("Left");
ButtonField right=new ButtonField("Right");
JustifiedHorizontalFieldManager j=new JustifiedHorizontalFieldManager(left,right, true);
hfm.add(j);
add(hfm);
The JustifiedHorizontalFieldManager class is given below -
public class JustifiedHorizontalFieldManager extends Manager
{
private static final int SYSTEM_STYLE_SHIFT = 32;
public Field _leftField;
public Field _rightField;
private boolean _giveLeftFieldPriority;
public JustifiedHorizontalFieldManager( Field leftField, Field rightField, boolean giveLeftFieldPriority )
{
this( leftField, rightField, giveLeftFieldPriority, Field.USE_ALL_WIDTH );
}
public JustifiedHorizontalFieldManager( Field leftField, Field rightField, boolean giveLeftFieldPriority, long style )
{
super( style );
_leftField = leftField;
_rightField = rightField;
add( _leftField );
add( _rightField );
_giveLeftFieldPriority = giveLeftFieldPriority;
}
public JustifiedHorizontalFieldManager( boolean giveLeftFieldPriority, long style )
{
super( style );
_giveLeftFieldPriority = giveLeftFieldPriority;
}
public void addLeftField( Field field )
{
if( _leftField != null ) {
throw new IllegalStateException();
}
_leftField = field;
add( _leftField );
}
public void addRightField( Field field )
{
if( _rightField != null ) {
throw new IllegalStateException();
}
_rightField = field;
add( _rightField );
}
public int getPreferredWidth()
{
return _leftField.getPreferredWidth() + _rightField.getPreferredWidth();
}
public int getPreferredHeight()
{
return Math.max( _leftField.getPreferredHeight(), _rightField.getPreferredHeight() );
}
protected void sublayout( int width, int height )
{
Field firstField;
Field secondField;
if( _giveLeftFieldPriority ) {
firstField = _leftField;
secondField = _rightField;
} else {
firstField = _rightField;
secondField = _leftField;
}
int maxHeight = 0;
int availableWidth = width;
availableWidth -= _leftField.getMarginLeft();
availableWidth -= Math.max( _leftField.getMarginRight(), _rightField.getMarginLeft() );
availableWidth -= _rightField.getMarginRight();
layoutChild( firstField, availableWidth, height - firstField.getMarginTop() - firstField.getMarginBottom() );
maxHeight = Math.max( maxHeight, firstField.getMarginTop() + firstField.getHeight() + firstField.getMarginBottom() );
availableWidth -= firstField.getWidth();
layoutChild( secondField, availableWidth, height - secondField.getMarginTop() - secondField.getMarginBottom() );
maxHeight = Math.max( maxHeight, secondField.getMarginTop() + secondField.getHeight() + secondField.getMarginBottom() );
availableWidth -= secondField.getWidth();
if( !isStyle( Field.USE_ALL_HEIGHT ) ) {
height = maxHeight;
}
if( !isStyle( Field.USE_ALL_WIDTH ) ) {
width -= availableWidth;
}
setPositionChild( _leftField, _leftField.getMarginLeft(), getFieldY( _leftField, height ) );
setPositionChild( _rightField, width - _rightField.getWidth() - _rightField.getMarginRight(), getFieldY( _rightField, height ) );
setExtent( width, height );
}
private int getFieldY( Field field, int height )
{
switch( (int)( ( field.getStyle() & FIELD_VALIGN_MASK ) >> SYSTEM_STYLE_SHIFT ) ) {
case (int)( FIELD_BOTTOM >> SYSTEM_STYLE_SHIFT ):
return height - field.getHeight() - field.getMarginBottom();
case (int)( FIELD_VCENTER >> SYSTEM_STYLE_SHIFT ):
return field.getMarginTop() + ( height - field.getMarginTop() - field.getHeight() - field.getMarginBottom() ) / 2;
default:
return field.getMarginTop();
}
}
public Field getLeftField()
{
return _leftField;
}
public Field getRightField()
{
return _rightField;
}
public void replace( Field oldField, Field newField )
{
if( oldField == newField ) {
// Nothing to do
return;
}
if( oldField == _leftField ) {
_leftField = newField;
} else if( oldField == _rightField ) {
_rightField = newField;
}
add( newField );
delete( oldField );
}
}
Even simpler if you want:
yourHorizontalFieldManager.add(leftButton);
rightButton.setPosition(Display.getWidth()-leftButton.getPrefferedWidth()-rightButton.getPreferredWidth());
yourHorizontalFieldManager.add(rightButton);
See also this