Cannot scroll up in Windows console using winapi and kernel32 - winapi

I need to scroll through the Windows console. For that, I'm using code from a Microsoft C example that I've rewritten in Rust. I make use of the winapi and kernel32 crates. I know the code is not written according to the Rust guidelines, it is just for demonstration purposes only:
extern crate kernel32;
extern crate winapi;
use std::mem;
fn main() {
for i in 0..100 {
println!("Just some data to scroll over {}", i);
}
scroll_up(10);
}
pub fn scroll_up(rows: i16) {
let hStdout: winapi::HANDLE;
let mut csbiInfo: winapi::CONSOLE_SCREEN_BUFFER_INFO = unsafe { mem::zeroed() };
let mut srctWindow: winapi::SMALL_RECT = unsafe { mem::zeroed() };
unsafe {
// Get the current screen buffer size and window position.
hStdout = kernel32::GetStdHandle(winapi::STD_OUTPUT_HANDLE);
kernel32::GetConsoleScreenBufferInfo(hStdout, &mut csbiInfo);
}
// Set srctWindow to the current window size and location.
srctWindow = csbiInfo.srWindow;
// Check whether the window is too close to the screen buffer top
if srctWindow.Top >= rows {
srctWindow.Top -= rows; // move top up
srctWindow.Bottom -= rows; // move bottom up
unsafe {
if (kernel32::SetConsoleWindowInfo(hStdout, winapi::TRUE, &srctWindow) == 1) {
// println!("SUCSESS");
} else {
println!("failed");
}
}
} else {
println!("failed");
}
}
pub fn scroll_down(rows: i16) {
let hStdout: winapi::HANDLE;
let mut csbiInfo: winapi::CONSOLE_SCREEN_BUFFER_INFO = unsafe { mem::zeroed() };
let mut srctWindow: winapi::SMALL_RECT = unsafe { mem::zeroed() };
unsafe {
// Get the current screen buffer size and window position.
hStdout = kernel32::GetStdHandle(winapi::STD_OUTPUT_HANDLE);
kernel32::GetConsoleScreenBufferInfo(hStdout, &mut csbiInfo);
}
// Set srctWindow to the current window size and location.
srctWindow = csbiInfo.srWindow;
// Check whether the window is too close to the screen buffer top
if srctWindow.Bottom < csbiInfo.dwSize.Y - rows {
srctWindow.Top += rows; // move top down
srctWindow.Bottom += rows; // move bottom down
unsafe {
if (kernel32::SetConsoleWindowInfo(hStdout, winapi::TRUE, &srctWindow) == 1) {
// println!("SUCSESS");
} else {
println!("failed");
}
}
} else {
println!("failed");
}
}
I can scroll down n lines:
I can not scroll up n lines. What could possibly go wrong here?
Cargo dependencies:
winapi = "0.2.8"
kernel32-sys = "0.2.1"

Related

strange process names when trying to get a PID in rust with the Windows api

Hello my goal is to create a rust function which takes a process name as string and returns a PID.
I came up with this function:
pub unsafe fn get_proc_id(proc_name: String) -> u32 {
let mut proc_id: u32 = 0;
let mut h_snap = windows::Win32::System::Diagnostics::ToolHelp::CreateToolhelp32Snapshot(
TH32CS_SNAPPROCESS,
0,
);
let h_snap = match h_snap {
Ok(t) => t,
Err(e) => panic!("eror {}", e),
};
let mut proc_entry: PROCESSENTRY32 = PROCESSENTRY32 {
..PROCESSENTRY32::default()
};
proc_entry.dwSize = std::mem::size_of::<PROCESSENTRY32>() as u32;
let entry_ptr = &mut proc_entry as *mut PROCESSENTRY32;
if windows::Win32::System::Diagnostics::ToolHelp::Process32First(h_snap, entry_ptr).as_bool() {
loop {
let mut proc_exe_string: String = String::new();
if proc_exe_string.eq(&proc_name) {
proc_id = proc_entry.th32ProcessID;
break;
}
for e in proc_entry.szExeFile {
if e.0 != 0 {
proc_exe_string.push(e.0 as char)
}
}
println!("{}", proc_exe_string);
if !Process32Next(h_snap, entry_ptr).as_bool() {
break;
}
}
}
CloseHandle(h_snap);
return proc_id; }
The function prints some strange process names. for example I'm looking for "ac_client.exe" however the function shows this process as ac_client.exeexe.exeee and this is similar for most process names. some other examples:
chrome.exexeexe.exeee
Discord.exer.exee.exee

Global `comptime var` in Zig

In Zig, I can do this with no problems:
fn foo() void {
comptime var num: comptime_int = 0;
num += 1;
}
But when I try declaring the variable outside of a function, I get a compile error:
comptime var num: comptime_int = 0;
fn foo() void {
num += 1;
}
fn bar() void {
num += 2;
}
error: expected block or field, found 'var'
Zig version: 0.9.0-dev.453+7ef854682
Use the method used in zorrow. It defines the variable in a function (a block works too), then it returns a struct with functions for accessing it.
You can create a struct that defines get and set functions:
const num = block_name: {
comptime var self: comptime_int = 0;
const result = struct {
fn get() comptime_int {
return self;
}
fn increment(amount: comptime_int) void {
self += amount;
}
};
break :block_name result;
};
fn foo() void {
num.increment(1);
}
fn bar() void {
num.increment(2);
}
In the future, you will be able to use a const with a pointer to the mutable value, and the method shown above will no longer be allowed by the compiler: https://github.com/ziglang/zig/issues/7396

Using winapi in Rust to get a bitmap from a window

.. Hi, I have this code :
#[cfg(windows)] extern crate winapi;
use winapi::um::winuser::{FindWindowW, GetClientRect, GetWindowDC, GetDC, ReleaseDC};
use winapi::um::wingdi::{CreateBitmap, CreateCompatibleBitmap, CreateCompatibleDC, SelectObject, GetObjectW, SaveDC, DeleteDC, DeleteObject};
use std::ptr::null_mut;
use std::mem::zeroed;
use std::ffi::OsStr;
use std::iter::once;
use std::os::windows::ffi::OsStrExt;
#[cfg(windows)]
fn find_window(name: &str) {
let window: Vec<u16> = OsStr::new(name).encode_wide().chain(once(0)).collect();
let hwnd = unsafe { FindWindowW(null_mut(), window.as_ptr()) };
if hwnd != null_mut() {
println!("Window found");
let mut my_rect = unsafe { zeroed::<winapi::shared::windef::RECT>() };
let _client_rect = unsafe { GetClientRect(hwnd, &mut my_rect) };
let w = my_rect.right - my_rect.left;
let h = my_rect.bottom - my_rect.top;
let hwnd_dc = unsafe { GetWindowDC(hwnd) };
let mem_dc = unsafe { CreateCompatibleDC(hwnd_dc) };
let bmp = unsafe { CreateCompatibleBitmap(mem_dc, w, h) };
//SelectObject(mem_dc, bmp); <== Problem is here
//DeleteObject(bmp); <== Same problem here
unsafe { DeleteDC(mem_dc) };
unsafe { ReleaseDC(hwnd, hwnd_dc) };
}
else {
println!("Window not found");
}
}
fn main() {
find_window("Firefox"); // just for test
}
If I cargo run this, I get :
SelectObject(mem_dc, bmp);
| ^^^ expected enum `std::ffi::c_void`, found enum `winapi::shared::windef::HBITMAP__`
So I get it, it doesn't want that bitmap pointer, but in the win32 documentation, it says that this function (SelectObject) accepts a Device Context (mem_dc) and an object created by some function like CreateCompatibleBitmap.
https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-selectobject
The binding in Rust accepts the two same arguments but it seems to want that std::ffi::c_void but looking a the Rust doc, I don't get what it is exactly.
Can you help me finding what's wrong ? Thanks.
Add:
use winapi::shared::windef::{HBITMAP, HBITMAP__, HGDIOBJ, HWND, POINT, RECT, SIZE};
...
unsafe {SelectObject(mem_dc, bmp as HGDIOBJ)};
unsafe {DeleteObject(bmp as HGDIOBJ)};

QDockWidget does not remember floating size and location when IsFloat is toggled

QDockWidget has a feature where you can double click on the title bar and the dock will toggle to a floating window and back to its docked state. The problem is if you move and resize the floating window and then toggle back to the dock and then back to floating again, your position and size are lost.
I've looked for solutions to resize and move a QDockWidget and I've taken a look at the Qt source code for QDockWidget. I've created a small subclass of QDockWidget that appears to solve the problem. It overrides the mouseDoubleClick, resize and move events, filtering out the unwanted "random" resizing and positioning by Qt and stores the information about screen, position and size in a struct that I store in QSettings for persistence between sessions.
// header
#include <QDockWidget>
#include "global.h"
class DockWidget : public QDockWidget
{
Q_OBJECT
public:
DockWidget(const QString &title, QWidget *parent = nullptr);
QSize sizeHint() const;
void rpt(QString s);
struct DWLoc {
int screen;
QPoint pos;
QSize size;
};
DWLoc dw;
bool ignore;
protected:
bool event(QEvent *event);
void resizeEvent(QResizeEvent *event);
void moveEvent(QMoveEvent *event);
};
// cpp
#include "dockwidget.h"
DockWidget::DockWidget(const QString &title, QWidget *parent)
: QDockWidget(title, parent)
{
ignore = false;
}
bool DockWidget::event(QEvent *event)
{
if (event->type() == QEvent::MouseButtonDblClick) {
ignore = true;
setFloating(!isFloating());
if (isFloating()) {
// move and size to previous state
QRect screenres = QApplication::desktop()->screenGeometry(dw.screen);
move(QPoint(screenres.x() + dw.pos.x(), screenres.y() + dw.pos.y()));
ignore = false;
adjustSize();
}
ignore = false;
return true;
}
QDockWidget::event(event);
return true;
}
void DockWidget::resizeEvent(QResizeEvent *event)
{
if (ignore) {
return;
}
if (isFloating()) {
dw.screen = QApplication::desktop()->screenNumber(this);
QRect r = geometry();
QRect a = QApplication::desktop()->screen(dw.screen)->geometry();
dw.pos = QPoint(r.x() - a.x(), r.y() - a.y());
dw.size = event->size();
}
}
QSize DockWidget::sizeHint() const
{
return dw.size;
}
void DockWidget::moveEvent(QMoveEvent *event)
{
if (ignore || !isFloating()) return;
dw.screen = QApplication::desktop()->screenNumber(this);
QRect r = geometry();
QRect a = QApplication::desktop()->screen(dw.screen)->geometry();
dw.pos = QPoint(r.x() - a.x(), r.y() - a.y());
dw.size = QSize(r.width(), r.height());
}
While this appears to be working is there a simpler way to accomplish this? What do I do if a QDockWidget was on a screen that is now turned off?

Is there a way to do a for loop that is neither iterative nor linear?

Can I write a Rust for loop equivalent to this C code:
for(int i = 2; i <= 128; i=i*i){
//do something
}
I'm only seeing things like
for i in 0..128 { /* do something */ }
or
let v = vec![0, 1, 2, /* ... */ ];
for i in v.iter() { /* do something */ }
Should I just use a while loop?
You can always create a custom iterator that does whatever unique sequence you need:
struct Doubling {
current: u64,
max: u64,
}
impl Iterator for Doubling {
type Item = u64;
fn next(&mut self) -> Option<Self::Item> {
if self.current > self.max {
None
} else {
let v = Some(self.current);
self.current *= 2;
v
}
}
}
fn main() {
let iter = Doubling { current: 2, max: 128 };
let values: Vec<_> = iter.collect();
println!("{:?}", values);
}
It's important to recognize that this logic (like the original C!) has nasty edge cases when the value is doubled beyond the size of the type.
In this particular case, you can also recognize that you have an exponential series:
fn main() {
let iter = (1..8).map(|p| 2i32.pow(p));
let values: Vec<_> = iter.collect();
println!("{:?}", values);
}
If you want to get really experimental, check out Lazy sequence generation in Rust. Adapted here:
#![feature(generators, generator_trait, conservative_impl_trait)]
use std::ops::{Generator, GeneratorState};
fn doubling(mut start: u64, max: u64) -> impl Iterator<Item = u64> {
GeneratorIteratorAdapter(move || {
while start <= max {
yield start;
start *= 2;
}
})
}
fn main() {
let iter = doubling(2, 128);
let sum: Vec<_> = iter.collect();
println!("{:?}", sum);
}
/* copy-pasta */
struct GeneratorIteratorAdapter<G>(G);
impl<G> Iterator for GeneratorIteratorAdapter<G>
where
G: Generator<Return = ()>,
{
type Item = G::Yield;
fn next(&mut self) -> Option<Self::Item> {
match self.0.resume() {
GeneratorState::Yielded(x) => Some(x),
GeneratorState::Complete(_) => None,
}
}
}
can I write a for loop equivalent to this C code:
That specifically, yes:
extern crate itertools;
for i in itertools::iterate(2, |&i| i*i).take_while(|&i| i <= 128) {
// do something
}
But in general, no. There is no single, direct equivalent to all possible uses of C's for loop. If there's no way to write it using iterators then yes, you need to use a more general loop form:
{
let mut i = 2;
while i <= 128 {
// do something
i = i*i;
}
}

Resources