Skip to content

Instantly share code, notes, and snippets.

@yonran
Created May 12, 2015 04:58
Show Gist options
  • Save yonran/706f84f0d489a47926cd to your computer and use it in GitHub Desktop.
Save yonran/706f84f0d489a47926cd to your computer and use it in GitHub Desktop.
//! cl.exe /Tp listviwe_setselectionmark.cpp User32.lib ComCtl32.lib Ole32.lib
#define STRICT
#define UNICODE
#define _UNICODE
#include <windows.h>
#include <windowsx.h>
#include <ole2.h>
#include <commctrl.h>
#include <shlwapi.h>
#include <shlobj.h>
#include <shellapi.h>
#include <stdlib.h> // rand
HINSTANCE g_hinst;
const WORD IDM_SELECTRANDOM = 1;
class Window
{
public:
HWND GetHWND() { return m_hwnd; }
protected:
virtual LRESULT HandleMessage(
UINT uMsg, WPARAM wParam, LPARAM lParam);
virtual void PaintContent(PAINTSTRUCT *pps) { }
virtual LPCTSTR ClassName() = 0;
virtual BOOL WinRegisterClass(WNDCLASS *pwc)
{ return RegisterClass(pwc); }
virtual ~Window() { }
HWND WinCreateWindow(DWORD dwExStyle, LPCTSTR pszName,
DWORD dwStyle, int x, int y, int cx, int cy,
HWND hwndParent, HMENU hmenu)
{
Register();
return CreateWindowEx(dwExStyle, ClassName(), pszName, dwStyle,
x, y, cx, cy, hwndParent, hmenu, g_hinst, this);
}
private:
void Register();
void OnPaint();
void OnPrintClient(HDC hdc);
static LRESULT CALLBACK s_WndProc(HWND hwnd,
UINT uMsg, WPARAM wParam, LPARAM lParam);
protected:
HWND m_hwnd;
};
void Window::Register()
{
WNDCLASS wc;
wc.style = 0;
wc.lpfnWndProc = Window::s_WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = g_hinst;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = ClassName();
WinRegisterClass(&wc);
}
LRESULT CALLBACK Window::s_WndProc(
HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
Window *self;
if (uMsg == WM_NCCREATE) {
LPCREATESTRUCT lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam);
self = reinterpret_cast<Window *>(lpcs->lpCreateParams);
self->m_hwnd = hwnd;
SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LPARAM>(self));
} else {
self = reinterpret_cast<Window *>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
}
if (self) {
return self->HandleMessage(uMsg, wParam, lParam);
} else {
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
LRESULT Window::HandleMessage(
UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LRESULT lres;
switch (uMsg) {
case WM_NCDESTROY:
lres = DefWindowProc(m_hwnd, uMsg, wParam, lParam);
SetWindowLongPtr(m_hwnd, GWLP_USERDATA, 0);
delete this;
return lres;
case WM_PAINT:
OnPaint();
return 0;
case WM_PRINTCLIENT:
OnPrintClient(reinterpret_cast<HDC>(wParam));
return 0;
}
return DefWindowProc(m_hwnd, uMsg, wParam, lParam);
}
void Window::OnPaint()
{
PAINTSTRUCT ps;
BeginPaint(m_hwnd, &ps);
PaintContent(&ps);
EndPaint(m_hwnd, &ps);
}
void Window::OnPrintClient(HDC hdc)
{
PAINTSTRUCT ps;
ps.hdc = hdc;
GetClientRect(m_hwnd, &ps.rcPaint);
PaintContent(&ps);
}
class RootWindow : public Window
{
public:
virtual LPCTSTR ClassName() { return TEXT("Scratch"); }
static RootWindow *Create();
protected:
LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT OnCreate();
private:
HWND m_hwndChild;
};
LRESULT RootWindow::OnCreate()
{
this->m_hwndChild = CreateWindowEx(
0, /*dwExStyle*/
WC_LISTVIEW,
TEXT("List view"),
WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP | LVS_REPORT | LVS_SHOWSELALWAYS, /*dwStyle*/
0,
0,
0, // width
0, // height
this->m_hwnd, // parent
NULL, // menu or control id
g_hinst,
NULL // lparam
);
if (! this->m_hwndChild) {
return -1;
}
ListView_SetExtendedListViewStyleEx(this->m_hwndChild, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
LVCOLUMN column;
column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
column.fmt = LVCFMT_LEFT;
column.iSubItem = 0;
column.pszText = TEXT("Column"),
column.cx = 50;
if (-1 == ListView_InsertColumn(this->m_hwndChild, 0, &column)) {
return -1;
}
LVITEM lvins;
lvins.iItem = INT_MAX; // after every existing item; actual index will be returned
lvins.mask = LVIF_TEXT;
lvins.iSubItem = 0;
lvins.pszText = TEXT("One");
if (-1 == ListView_InsertItem(this->m_hwndChild, &lvins)) {
return -1;
}
lvins.pszText = TEXT("Two");
if (-1 == ListView_InsertItem(this->m_hwndChild, &lvins)) {
return -1;
}
lvins.pszText = TEXT("Three");
if (-1 == ListView_InsertItem(this->m_hwndChild, &lvins)) {
return -1;
}
lvins.pszText = TEXT("Four");
if (-1 == ListView_InsertItem(this->m_hwndChild, &lvins)) {
return -1;
}
lvins.pszText = TEXT("Five");
if (-1 == ListView_InsertItem(this->m_hwndChild, &lvins)) {
return -1;
}
lvins.pszText = TEXT("Six");
if (-1 == ListView_InsertItem(this->m_hwndChild, &lvins)) {
return -1;
}
return 0;
}
LRESULT RootWindow::HandleMessage(
UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg) {
case WM_CREATE:
return OnCreate();
case WM_NCDESTROY:
// Death of the root window ends the thread
PostQuitMessage(0);
break;
case WM_SIZE:
if (m_hwndChild) {
SetWindowPos(m_hwndChild, NULL, 0, 0,
GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam),
SWP_NOZORDER | SWP_NOACTIVATE);
}
return 0;
case WM_SETFOCUS:
if (m_hwndChild) {
SetFocus(m_hwndChild);
}
return 0;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDM_SELECTRANDOM:
for (int index = ListView_GetNextItem(this->m_hwndChild, -1, LVNI_SELECTED); index != -1;
index = ListView_GetNextItem(this->m_hwndChild, index, LVNI_SELECTED)) {
ListView_SetItemState(this->m_hwndChild, index, 0, LVNI_SELECTED);
}
int index = rand() % ListView_GetItemCount(this->m_hwndChild);
ListView_SetItemState(this->m_hwndChild, index, LVNI_SELECTED, LVNI_SELECTED);
ListView_SetSelectionMark(this->m_hwndChild, index);
ListView_EnsureVisible(this->m_hwndChild, index, false);
SetFocus(this->m_hwndChild);
return 0;
}
break;
}
return __super::HandleMessage(uMsg, wParam, lParam);
}
RootWindow *RootWindow::Create()
{
RootWindow *self = new RootWindow();
if (self && self->WinCreateWindow(0,
TEXT("Scratch"), WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL)) {
return self;
}
delete self;
return NULL;
}
int PASCAL
WinMain(HINSTANCE hinst, HINSTANCE, LPSTR, int nShowCmd)
{
g_hinst = hinst;
if (SUCCEEDED(CoInitialize(NULL))) {
InitCommonControls();
RootWindow *prw = RootWindow::Create();
ACCEL accel[1];
accel[0].fVirt = FCONTROL | FVIRTKEY;
accel[0].key = 'R';
accel[0].cmd = IDM_SELECTRANDOM;
HACCEL haccel = CreateAcceleratorTable(accel, 1);
if (prw) {
ShowWindow(prw->GetHWND(), nShowCmd);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
if (!TranslateAccelerator(prw->GetHWND(), haccel, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
DestroyAcceleratorTable(haccel);
CoUninitialize();
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment