|
I'm sure you are, still bloody irritating though...
|
|
|
|
|
You think Richard is irritating?
|
|
|
|
|
Yep, but don't tell him!
|
|
|
|
|
Ok, take my 1 .
I can't tell you why
I can't tell you why
Veni, vidi, vici.
|
|
|
|
|
In a rather rough approach you may let the user write the full name of the serial port into an edit box (say myEditBox ) and use that string as argument of open_host_port , that is as simple as (assuming a ANSI build):
CString portname;
myEditBox.GetWindowText(portname);
COMstream = open_host_port(portname);
Veni, vidi, vici.
|
|
|
|
|
but open_host_port () is defined as
portstream_fd open_host_port(char *portname)
|
|
|
|
|
Well, that is a open_host_port fault.
Why - the fresh Hell - the function needs a not-const string?
However
COMstream = open_host_port((LPSTR)(LPCSTR) testCStr);
should do the trick.
BTW I ask you once again (I'm curious): what library are you using?
Veni, vidi, vici.
|
|
|
|
|
thank you CPallini. that was really helpful.
|
|
|
|
|
You are welcome.
Veni, vidi, vici.
|
|
|
|
|
I have an dialog with two static methods :
static void StartSomething();
static void EndSomething();
void CMyDialog::StartSomething()
{
GetDlgItem(IDOK)->EnableWindow(FALSE); }
void CMyDialog::EndSomething()
{
GetDlgItem(IDOK)->EnableWindow(); }
How can I disable/enable dialog's OK button from static dialog methods ?
Thank you.
|
|
|
|
|
you will have to find a way to give the static methods a 'this' pointer for the dialog you want to control, or the HWND of the dlg.
|
|
|
|
|
When I've used class objects to represent windows in the past, that's just what I've done.
The way I implemented it was to use the following 3 lines of code:
SetWindowLong(mHwnd, GWL_USERDATA, (long)((void*)this));
mOldWndProc = (WNDPROC)GetWindowLong(mHwnd, GWL_WNDPROC);
SetWindowLong(mHwnd, GWL_WNDPROC, (long)stWinMsgHandler);
This allows the static method stWinMsgHandler to obtain the correct instance of the class that's being used to handle a particular window, as below:
LRESULT CALLBACK cStaticLink::stWinMsgHandler(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
cStaticLink *pWnd;
pWnd = (cStaticLink*)GetWindowLong(hwnd, GWL_USERDATA);
if (pWnd)
return pWnd->WndProc(hwnd, uMsg, wParam, lParam);
else
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
|
|
|
|
|
Thank you all, I solve my problem, you are very kind. Got my 5 all of you !!!
|
|
|
|
|
Sound good, but can you tell me how to use 'this' pointer or HWND to access OK button ?
|
|
|
|
|
once you have a pointer to the dialog:
dlg->GetDlgItem(IDOK)->EnableWindow(FALSE);
|
|
|
|
|
Why are you using static functions for non-static actions?
Programming is work, it isn't finger painting. Luc Pattyn
|
|
|
|
|
Those static functions setup something into a listcontrol, and while this listctrl is in edit mode, I want to block user to end the dialog with unfinished values ...
|
|
|
|
|
You don't need static functions to do that.
Programming is work, it isn't finger painting. Luc Pattyn
|
|
|
|
|
Hi folks,
I'm working on a program that reads a text file which has columns of dates, times and associated values, then sends the columns to an excel sheet. The entire file follows the same pattern.
Text file sample (there's a total of 21 columns, I've deleted some to make it look less messy):
2012-05-14 14:08:12.498 8 InfoMSG1 N 2.719 2994 2153 2089 {InfoMSG2}
2012-08-14 14:08:38.644 8 InfoMSG3 N 2.974 6.732 9.577 10.596 {InfoMSG4}
At the moment, I'm using a fairly inelegant solution of breaking each sentence into tokens delimited by whitespace and storing each column in a separate array as follows:
string line;
string *col1, *col2, *col4, *col5, *col21;
col1 = new string[fileLength];
col2 = new string[fileLength];
col4 = new string[fileLength];
col5 = new string[fileLength];
col21 = new string[fileLength];
while(getline(file, line))
{
std::stringstream linestream(line);
linestream >> col1[i] >> col2[i] >> col3[i] >> col4[i] >> col5[i] >> col6[i] >> col7[i] >> col8[i] >> col9[i] >> col10[i] >> col11[i];
linestream >> col11[i] >> col13[i] >> col14[i] >> col15[i] >> col16[i] >> col17[i] >> col18[i] >> col19[i] >> col20[i] >> col21[i];
i++;
}
In my research of the COM interface process from C++ to Excel I haven't been able to find a method of passing single byte strings to excel. The only method I've been able to have any success with is detailed in this MSDN article -
http://support.microsoft.com/kb/216686
It uses a VARIANT safearray to pass data to Excel, and the only way I can see to use my arrays as above is to convert the std::strings in each element first to wstrings, then to BSTR.
I would think there's probably a better way to do this conversion but haven't come up with one.
Anyway, my conversion form single byte to wide string is achieved using the following function:
wstring stws(const string &src_string)
{
size_t src_len = src_string.length();
if(0 == src_len)
return L"";
wchar_t *buf = new(std::nothrow) wchar_t[src_len + 1];
if(0 == buf)
return L"";
mbstowcs(buf, src_string.c_str(), src_len);
buf[src_len] = L'\0';
wstring final_string = buf;
if(0 != buf)
delete [] buf;
return final_string;
}
The further conversion from wide string to BSTR is carried out like so:
wcol1 = new wstring[fileLength];
wcol2 = new wstring[fileLength];
wcol4 = new wstring[fileLength];
wcol5 = new wstring[fileLength];
wcol21 = new wstring[fileLength];
bcol1 = new BSTR[fileLength];
bcol2 = new BSTR[fileLength];
bcol4 = new BSTR[fileLength];
bcol5 = new BSTR[fileLength];
bcol21 = new BSTR[fileLength];
for(int i=0; i<10; i++)
{
wcol1[i] = stws(col1[i]);
wcol2[i] = stws(col2[i]);
wcol4[i] = stws(col4[i]);
wcol5[i] = stws(col5[i]);
wcol21[i] = stws(col21[i]);
bcol1[i] = SysAllocString(wcol1[i].c_str());
bcol2[i] = SysAllocString(wcol1[i].c_str());
bcol4[i] = SysAllocString(wcol1[i].c_str());
bcol5[i] = SysAllocString(wcol1[i].c_str());
bcol21[i] = SysAllocString(wcol1[i].c_str());
}
I've printed the BSTR values to the console using wcout to confirm that they are correct.
Now, to pass this data into an excel sheet. I'm using the method outlined in the MSDN article linked above, creating a safe array with my list of values from the BSTR arrays:
VARIANT arr;
arr.vt = VT_ARRAY | VT_VARIANT;
{
SAFEARRAYBOUND sab[2];
sab[0].lLbound = 1; sab[0].cElements = 10;
sab[1].lLbound = 1; sab[1].cElements = 1;
arr.parray = SafeArrayCreate(VT_VARIANT, 2, sab);
}
for(int i=0; i<10; i++) {
for(int j=0; j<2; j++) {
VARIANT tmp;
tmp.vt = VT_BSTR;
tmp.bstrVal = bcol2[i];
long indices[] = {i,j};
SafeArrayPutElement(arr.parray, indices, (void *)&tmp);
}
}
Then I do the usual COM tasks, creating a new Workbook, acquiring the Active Worksheet, getting a range object, before setting the values in the range as follows:
AutoWrap(DISPATCH_PROPERTYPUT, NULL, pXlRange, L"Value", 1, arr);
For the scenario described above, where I only copy a single column to excel at a time, what I have does the trick.
My major problem at this stage is finding a way to loop in the two dimensions of the safearray to copy the rest of the columns at the same time. I know I can do it by creating a safearray for each column following a similarly inelegant approach to how I dealt with splitting the data into columns in the first place, but I'm sure there's a better way to do it than that.
Any help would be greatly appreciated, ty.
|
|
|
|
|
keane2097 wrote: Anyway, my conversion form single byte to wide string is achieved using the following function:
Would A2W() be of any help?
"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
"Show me a community that obeys the Ten Commandments and I'll show you a less crowded prison system." - Anonymous
|
|
|
|
|
Hi David, I'm away from my computer now so can't check, but I'm guessing the A2W() function carries out the single-byte to wide conversion for me?
If so it will be a help by replacing my own function with a presumably more well tested one so thanks for that.
I'm going to hold out hope that it does the entire conversion to BSTR until I can disprove the theory which will also improve my mood for a couple of hours at least so thanks for that too
|
|
|
|
|
I've done something similar to this a couple of years back. In my case I was doing it from VBA, though (I guess) it shouldn't matter.
I was able to fill the cells in a range with the values contained in a 2D array.
So, rather than 1 call per column it was 1 call for the whole lot.
I'll have a poke around in the morning and see if I still have a copy of the code lying around. (I may very well not, since it was for a project at an old job)
Fantastically articulate post btw.
|
|
|
|
|
Ha! Thanks for the compliment
If you do manage to dig out that old code I'd be much obliged, thanks.
|
|
|
|
|
Pleasure. It's unfriendly to bash the inept - but there's nothing wrong with complimenting those at the opposite end of the spectrum, methinks!
Can't be bothered to find the old code (Gawd knows how many gigs of data I'd have to sift through)
BUT, I can offer you some brand-new freshly written code
Here's something that fills in 100 (iSize*iSize cells) in 1 fell swoop.
Sub test1()
Const iSize = 10
Dim myArray(1 To iSize, 1 To iSize)
Dim iRow As Integer, iCol As Integer
iRow = 1
For iCol = 1 To iSize
myArray(iRow, iCol) = "Column " + CStr(iCol)
Next iCol
curCellNum = 1
For iRow = 2 To iSize
For iCol = 1 To iSize
myArray(iRow, iCol) = curCellNum
curCellNum = curCellNum + 1
Next iCol
Next iRow
Cells.Range(Cells(1, 1), Cells(iSize, iSize)) = myArray
End Sub
Hope that's of some use.
|
|
|
|
|
|