Age | Commit message (Collapse) | Author |
|
|
|
For string lengths EXCLUDING NUL, I use len, whereas cb and cch are
used for string lengths INCLUDING NUL.
cb = byte count = sizeof(a) = narrow string length
cch = character count = sizeof(a)/sizeof(*a) = string length
cb and cch are equivalent for narrow strings. I prefer cch.
|
|
|
|
|
|
|
|
|
|
|
|
The user-defined conversion function makes the interface a lot simpler
AND safer.
|
|
I don't hate Hungarian notation. It has some very nice qualities. But
it also adds a lot of typing.
That said, not using it feels a bit... unsafe. I might go back on this
decision. We'll see.
|
|
(When the focused episode is near the end of the list.)
|
|
|
|
std::basic_string is nice, but it is not very ergonomic if everything
you really need is to automatically free C strings at end of scope.
I suppose I could have used std::unique_ptr for this, but I suspect
the ergonomics would be worse.
|
|
This style is more compact and quicker to read once you know what the
first two member in LVITEM are (mask and iItem).
|
|
This makes it much more ergonomic and less error-prone to look up list
view items.
|
|
See f7534e2.
|
|
swprintf_s excepts the NUMBER of characters, not the SIZE of the
buffer. The argument is named sizeOfBuffer in the documentation, but
don't let that fool you (like it did me).
Interestingly enough, this bug causes a crash ONLY when compiling
WITHOUT optimizations (at least on my system). The crash was
introduced in 3a133c4, where I removed the `static' attribute from
tszRating.
I guess the optimizer moves the memory around such that the memory
after the string happens to be unimportant.
|
|
|
|
|
|
Even though it is a fun challange in many ways, I think that,
realistically, it is probably not worth the complexity. The
Prolog backend isn't ANSI-compatible either.
|
|
|
|
|
|
This also fixes an off-by-one error leading to an out-of-bounds write.
|
|
This reverts much of 97f0a27.
1. It turns out not to be a good idea to resize the list view columns
based on the list view window's own rectangle, as it will change
depending on whether a scrollbar is visible. The problem is that
resizing the columns may add a horizontal scrollbar -- which in
turn may add a vertical scrollbar.
2. The WS_EX_CLIENTEDGE style does not look very good in "modern"
(non-classic) themes. In 97f0a27, I tried solving this by extending
the dimensions of the child windows such that their edges were
hidden. However, this type of overlapping causes problems with the
status bar. My new solution is to instead *reduce* the child
windows' dimensions. This achieves a visual impression similar to
the thicker (more well-designed) edges of the "classically themed"
list view control. To make it look even better, the main window
background is changed from COLOR_WINDOWFRAME (white) to
COLOR_WINDOW (light gray).
|
|
Turns out that SWI-Prolog's wide string functions, which I started
using in 03fe361, do not convert between narrow Prolog atoms and wide
C strings, as I mistakenly thought. Instead, they work with wide
Prolog atoms. In hindsight, it is not surprising.
|
|
This incidentally removes the need for the variable
template introduced by 21e96c6. I'm sure it will be
needed at some point, though.
|
|
The variable template could be generalized like this:
template <auto F, auto... A> const auto cache = F(A...);
and instantiated like:
cache<GetSystemMetrics, SM_CXVSCROLL>
It would still be limited to constant function arguments, which
usually isn't a problem for GetSystemMetrics, but might be for
other functions.
|
|
|
|
|
|
It's not very useful, but it's a fun exercise.
|
|
In warn_nil, the return value was undefined on exception -- I think.
While informative, the names throw_nil and warn_nil don't work very
well in conditionals:
if (warn_nil<f>(...)) g();
sounds like g should be called if f returns nil and a warning is
issued. But it is actually the other way around; g is called if f is
successful.
if (prefer<f>(...)) g();
sounds less like that.
|
|
Some of the checks are likely redundant, but the Windows API
documentation rarely makes it clear WHICH errors may be returned (and
under which circumstances) rather than simply WHETHER errors may be
returned (under any circumstances, including those that do not apply
in the given case).
|
|
|
|
Speaking of unclear documentation, it is not obvious whether it is
necessary for programs calling into Prolog to manually mark and
release strings. I suppose that it should be, if the same logic that
applies to terms apply to strings.
On the other hand, the stack in which the strings are stored belongs
to Prolog, and there is nothing that would prevent Prolog from
cleaning up the strings when called at a later time. I am not sure.
But better safe than sorry, I guess.
The Mark class acts like the Frame class. The constructor and
destructor are equivalent to the PL_STRINGS_MARK and
PL_STRINGS_RELEASE macros.
Unlike for 34c3280, I did not notice any differences in memory usage
after this change. Perhaps that is because it has no effect; perhaps
it is because Prolog's stack is very big.
|
|
|
|
A getter offers encapsulation, but it is also less transparent in a
sense. Thinking of ListView as a struct, it is natural to expose hWnd
as a public member variable.
|
|
|
|
It seems that "right-spaced" pointers are more widely used among C++
programmers.
|
|
Note that I did NOT add const to non-pointer/non-reference arguments
in function declarations (without a following definition), as they do
not mean anything there.
|
|
This avoids the use of TsmFromSz.
|
|
|
|
I.e. using std::basic_string<TCHAR> instead of TCHAR *. This removes
all unmanaged frees.
|
|
This avoids g_hWnd.
|
|
This is feasible now that the makedeps script exists to automatically
manage build dependencies (see 6034fe2, d00f8b3).
|
|
This is a bit safer and about as complex.
|
|
|
|
Height(DLVSIKEY) was incorrect. The argument to Height is supposed to
be a boolean value, in this case false. It happened to work because
DLVSIKEY is 0 (because Key is the 0th column in the data list view).
|
|
The rules for what messages are sent at window creation -- and in
which order -- are neither intuitive or clear. WM_CREATE can NOT be
relied upon to initialize global state required by handlers of other
messages (such as WM_GETMINMAXINFO, which seems to be sent before
WM_CREATE).
Thus, the better solution is to initialize everything using a CBT hook
before the window procedure is even run. Because CBTProc creates
(child): windows of its own, though, one must be careful to only run
the initialization once, which is done by checking g_hWnd.
|
|
|
|
|
|
I already hit upon some object-oriented programming patterns in
*listview.c, so I felt that it would be natural to use this as an
opportunity to learn C++.
|