Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
i have 2 edit control in dialog box. And onclick of Ok Button i want to compare this value with string.
case IDC_BUTTON1:
UINT WINAPI GetDlgItemText(
_In_ HWND hDlg,
_In_ int nIDDlgItem,
_Out_ LPTSTR lpString,
_In_ int nMaxCount
);
TCHAR szBuf[BUFF_LEN];
TCHAR szBuf1[BUFF_LEN];
GetDlgItemText(hDlg, IDC_EDIT1, szBuf, BUFF_LEN - 1);
GetDlgItemText(hDlg,IDC_EDIT2,szBuf1,BUFF_LEN-1);
now after that if condition check the value szBuf and szBuf1 but it say can not convert cont char to tchar how to convert this value.
The important details are leaking out in comments. That's too bad – the details should appear in the question. In particular you should at least have shown the line of code that performed the comparison and that led to the compiler error. And the compiler error should always be transcribed verbatim.
That said, it looks as though you are using either wcscmp or _tcscmp to perform the comparison. But you are passing szBuf which is a wide string for one argument, and a literal like "hello" for the other. The problem with that is that szBuf is a wide string and the literal is 8 bit, a const char*.
I hypothesise that you have written code this this:
int cmp = _tcscmp(szBuf, "Hello");
And the compiler objects because you have defined the UNICODE conditional and so _tcscmp expects both parameters to be of type const wchar_t*. The literal is not, it is const char*.
So the simple solution is to use a wide literal:
int cmp = _tcscmp(szBuf, _T("Hello"));
That said, I would not recommend using TCHAR in this day and age. I think it unlikely that you are still targeting Windows 98. Stick to the Windows native Unicode API and use wide strings. Declare your buffers like this:
wchar_t szBuf[BUFF_LEN];
And compare like this:
int cmp = wcscmp(szBuf, L"Hello");
Done that way it's much easier to understand what you are working with. Using TCHAR if you always compile with UNICODE defined is a pointless exercise that just results in obfuscated code.
Even better still though would be to avoid C strings as much as possible and use native C++ strings. For example std::wstring would be the obvious choice here. Clearly you need to use the C strings for the low-level Windows API calls, but as soon as they return you a value, transfer that to a C++ string and life will be so much simpler.
Related
I'm using the IDesktopWallpaper::SetWallpaper method from the windows crate. The second argument to this method is a PCWSTR(pointer) to the full path of an image that's meant to be set as the wallpaper. The problem is that the PCWSTR object is meant to be of type *const u16 not *const String. How can I get a PCWSTR object from a Path/String?
let path = "Path_to_image.jpg".to_string();
let ptr = &path as *const String;
let wallpaper = PCWSTR::from_raw(ptr);
// ^^^ expected raw pointer `*const u16`
// found raw pointer `*const String`
unsafe { desktop.SetWallpaper(None, wallpaper)};
When it comes to strings, Rust and Windows couldn't possibly disagree more. There's always going to be conversions involved when using Rust on Windows, and the best you can hope for is a crate that does this for you.
The windows crate doesn't just provide Rust mappings for Windows' API surface, it also contains a tiny library that addresses common issues when programming Windows with Rust, amongst which is string handling. A lot of thought went into string handling, and the result may seem somewhat anticlimactic: All string constants can be represented as HSTRING instances.
Consequently, HSTRING is the pivot point for string conversions in Rust for Windows. Its implementation has a sleuth of From trait implementations for Rust string types (all, I believe), with From implementations of all other Windows string types for HSTRING.
In this case, if path is of type Path you can simply construct an HSTRING from it, and pass it by reference. Everything else just happens due to implicit From trait invocations (namely From<&HSTRING> for PCWSTR):
unsafe { desktop.SetWallpaper(None, &HSTRING::from(path.as_os_str())) };
I noticed there are two ways of handling LPWSTR output types in the windows-rs crate; Both start with marshalling the string into a slice:
let len = (0..).take_while(|&i| *ptr.offset(i) != 0).count();
let slice = std::slice::from_raw_parts(ptr, len);
Then it seems we can do one of:
let output = OsString::from_wide(slice).to_string_lossy().into_owned()
or
let output = String::from_utf16_lossy(slice)
The first option I'm guessing is more correct, but in order to use it you have to bring std::os::windows::prelude::OsStringExt into scope. The problem for me right now is that prevents rust-analyzer from linting due to a bug: https://github.com/rust-analyzer/rust-analyzer/issues/6063
Using the later method sidesteps this to improve my development workflow. Is the later method likely cause me any problems?
I am writing code in Go to call some of the Windows trust and crypt dlls to verify file signatures. There are many constants in wincrypt.h that I have tried to port over verbatim but i've hit some issues with integer overflow.
For example, all of the error codes that can be returned from WinVerifyTrust are negative values. If I take one example, TRUST_E_NOSIGNATURE, this is defined in winerror.h as so: #define TRUST_E_NOSIGNATURE _HRESULT_TYPEDEF_(0x800B0100L). In my Go code, I have const TRUST_E_NOSIGNATURE = int32(0x800B0100) but when compiled the error is:
constant 2148204800 overflows int32
when I really expected the value to be -2146762496
So, my questions 1) why does it not wrap like it does in other languages 2) Is there anyway to have the constant still use the hex representation of the number or will I have to change the code to const TRUST_E_NOSIGNATURE = int32(-2146762496) which works ok but will require me to make this change in many other constants that I have ported?
You just set it:
const TRUST_E_NOSIGNATURE = int32(-2146762496)
Use hex if you wish:
const TRUST_E_NOSIGNATURE = int32(-0x7ff4ff00)
But for this, you're probably just using the wrong data type. Use a uint32 instead:
const TRUST_E_NOSIGNATURE = uint32(0x800B0100)
why does it not wrap like it does in other languages?
Because it wasn't designed that way. Go follows the philosophy of being as obvious and intuitive as possible. Silent wrapping is very non-intuitive.
I have asked a similar question before, but I realize that I can't make heads or tails of the macrology and templateness. I'm a C (rather than C++) programmer.
What does F() actually do? When does it stuff characters into pgmem (flash)? When does it pull characters out of pgmem? Does it cache them? How does it handle low-memory situations?
There are no templates involved, only function overloading. The F() macro does two things:
uses PSTR to ensure that the literal string is stored in flash memory (the code space rather than the data space). However, PSTR("some string") cannot be printed because it would receive a simple char * which represents a base address of the string stored in flash. Dereferencing that pointer would access some random characters from the same address in data. Which is why F() also...
casts the result of PSTR() to __FlashStringHelper*. Functions such as print and println are overloaded so that, on receiving a __FlashStringHelper* argument, they correctly dereference the characters in the flash memory.
BTW. For the ESP32 library, both of these functions are defined in the following files:
# PSTR : ../Arduino/hardware/espressif/esp32/cores/esp32/pgmspace.h
# F : ../Arduino/hardware/espressif/esp32/cores/esp32/WString.h
And the F(x):
// An abstract class used as a means to provide a unique pointer type
// but really has no body
class __FlashStringHelper;
#define F(string_literal) (reinterpret_cast<const __FlashStringHelper *>(PSTR(string_literal)))
...
Also for ESP32, PSTR(x) is not needed and is just x: #define PSTR(s) (s).
Looking at the Windows SDK, I found this #define directive for MAKEINTRESOURCEW:
#define MAKEINTRESOURCEW(i) ((LPWSTR)((ULONG_PTR)((WORD)(i))))
Can someone explain to me what the heck that means? For example, what would be the value of MAKEINTRESOURCEW(0)? (1)? (-1)?
The result of this macro will be pointer to long string with value equal to given parameter. You can see it by reading precompiler output (see /P C++ compiler options). All casting is required to compile this macro result, when LP[w]WSTR pointer is required, both in Win32 and x64 configurations.
Some Windows API, like LoadIcon, expect string pointer as their parameter. Possibly, these functions test the pointer value, and if it is less than some maximum, they interpret it as resource index, and not as string (problems of ugly C-style interface). So, this macro allows to pass WORD as string, without changing its value, with appropriate casting.
For the most part, it leaves the value unchanged, but converts it from an int to a pointer so it's acceptable to functions that expect to see a pointer. The intermediate casts widen the input int to the same size as a pointer, while ensuring against it's being sign extended. In case you care, ULONG_PTR is not a "ULONG POINTER" like you might guess -- rather, it's an unsigned long the same size as a pointer. Back before 64-bit programming became a concern, the definition was something like:
#define MAKEINTRESOURCE(i) (LPTSTR) ((DWORD) ((WORD) (i)))
Nowadays, they use ULONG_PTR, which is a 32-bit unsigned long for a 32-bit target, and a 64-bit unsigned long for a 64-bit target.
That's a macro that casts an argument i to a word, then casts that result to a pointer to an unsigned long, then again to a long pointer to a wide-character string.
Like other users said - it just casts an integer into a "pointer to a string".
The reason for this is the following: At the ancient times of Windows 3.0 people tried to be minimalistic as much as possible.
It was assumed that resources in the executable can have either string identifier or integer. Hence when you try to access such a resource - you specify one of the above, and the function distinguish what you meant automatically (by checking if the provided "pointer" looks like a valid pointer).
Since the function could not receive a "variable argument type" - they decided to make it receive LPCTSTR (or similar), whereas the actual parameter passed may be integer.
Another example from Windows API: A pointer to the window procedure. Every window has a window procedure (accessed via GetWindowLong with GWL_WNDPROC flag.
However sometimes it's just an integer which specifies what "kind" of a window is that.
Then there's a CallWindowProc which knows to distinguish those cases.